上篇文章ExtJs与WCF交互:生成树中阐述了用wcf产生json数据给extjs产生树控件的用法,本文将着重讲述如何用wcf+extjs+linq打造一个支持排序和列刷选的grid。闲话少叙 ,下面是操作步骤和实现效果图
第一步:在vs2008中创建一个支持.net framework 3.5的网站,此处之所以强调支持.net framework 3.5是为了使用linq
第二步:将运行时需要的Extjs的资源文件拷贝到项目目录,具体可见示例项目
第三步:假设在本机sql2005中存在数据库sharelist,里面有一个数据表stocks,效果如下:
数据库文件sharelist.mdf在示例项目db文件夹中。如果需要测试,可以将其附加到自己的sql2005数据库服务器中。
在网站项目中创建一个Linq To Sql类:DataClasses.dbml,方法如下如所示:
点击添加之后,出现下面的Linq To Sql向导
在本文只使用左面面板,在服务器资源管理器中添加对数据库sharelist的连接,效果如下:
点击数据表stocks,然后拖动stocks数据表到左面面板,拖动后效果如下:
点击stocks,然后更改类名称为Stock:
更改后效果为:
好,到此我们基本完成了linq to sql类的设计,我们在解决方案管理器中打开生成的类代码文件中,其中包括类:Stock ,为了使其能够被WCF使用
,对类添加DataContractAttribute,对属性添加DataMemberAttribute,添加好之后的代码为:

linq to sql类生成的代码并添加了wcf支持
#pragma warning disable 1591

//------------------------------------------------------------------------------

// <auto-generated>

// 此代码由工具生成。

// 运行库版本:2.0.50727.1433

//

// 对此文件的更改可能会导致不正确的行为,并且如果

// 重新生成代码,这些更改将会丢失。

// </auto-generated>

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Data.Linq;

using System.Data.Linq.Mapping;

using System.Linq;

using System.Linq.Expressions;

using System.Reflection;

[System.Data.Linq.Mapping.DatabaseAttribute(Name="sharelist")]

public partial class DataClassesDataContext : System.Data.Linq.DataContext



{


private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();



Extensibility Method DefinitionsExtensibility Method Definitions#region Extensibility Method Definitions

partial void OnCreated();

#endregion


public DataClassesDataContext() :

base(global::System.Configuration.ConfigurationManager.ConnectionStrings["sharelistConnectionString"].ConnectionString, mappingSource)


{

OnCreated();

}


public DataClassesDataContext(string connection) :

base(connection, mappingSource)


{

OnCreated();

}


public DataClassesDataContext(System.Data.IDbConnection connection) :

base(connection, mappingSource)


{

OnCreated();

}


public DataClassesDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :

base(connection, mappingSource)


{

OnCreated();

}


public DataClassesDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :

base(connection, mappingSource)


{

OnCreated();

}


public System.Data.Linq.Table<Stock> Stock


{

get


{

return this.GetTable<Stock>();

}

}

}


[Table(Name="dbo.stocks")]
[DataContract]
public partial class Stock



{


private string _company;


private double _price;


private double _change;


private double _changepercent;


private System.DateTime _lastupdated;


public Stock()


{

}


[Column(Storage="_company", DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
[DataMember]
public string company


{

get


{

return this._company;

}

set


{

if ((this._company != value))


{

this._company = value;

}

}

}


[Column(Storage="_price", DbType="Float NOT NULL")]
[DataMember]
public double price


{

get


{

return this._price;

}

set


{

if ((this._price != value))


{

this._price = value;

}

}

}


[Column(Storage="_change", DbType="Float NOT NULL")]
[DataMember]
public double change


{

get


{

return this._change;

}

set


{

if ((this._change != value))


{

this._change = value;

}

}

}


[Column(Storage="_changepercent", DbType="Float NOT NULL")]
[DataMember]
public double changepercent


{

get


{

return this._changepercent;

}

set


{

if ((this._changepercent != value))


{

this._changepercent = value;

}

}

}


[Column(Storage="_lastupdated", DbType="DateTime NOT NULL")]
[DataMember]
public System.DateTime lastupdated


{

get


{

return this._lastupdated;

}

set


{

if ((this._lastupdated != value))


{

this._lastupdated = value;

}

}

}

}

#pragma warning restore 1591


第四步:在网站项目中创建一个启用了Ajax的WCF服务:ArrayGridService.svc,然后将其中的类代码更改为:

using System;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.ServiceModel.Web;

using System.Collections.Generic;



[ServiceContract(Namespace = "")]

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

public class ArrayGridService



{

// 添加 [WebGet] 属性以使用 HTTP GET

[OperationContract]

[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "GET", UriTemplate = "GetStocks")]

public Stock[] GetStocks()


{

DataClassesDataContext dbContext = new DataClassesDataContext();

IQueryable<Stock> res = dbContext.Stock.Select(stock => stock);

return res.ToArray<Stock>();

}

// 在此处添加更多操作并使用 [OperationContract] 标记它们

}
在页面文件中,在<%@ ServiceHost中添加Factory="System.ServiceModel.Activation.WebServiceHostFactory",然后在web.config中将<enableWebScript/>替换成为<webHttp/>,注意这两个操作是必须的。到此wcf服务也准备齐备。
第五步:创建一个BasicGrid.aspx,然后在页面中添加extjs必要的链接和脚本支持,并添加页面元素,完成后的代码为:

BasicGrid.aspx页面文件

<%
@ Page Language="C#" AutoEventWireup="true" CodeFile="BasicGrid.aspx.cs" Inherits="BasicGrid" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>extjs+wcf+linq 打造grid</title>

<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css" />


<script type="text/javascript" src="adapter/ext/ext-base.js" charset="gb2312"></script>


<script type="text/javascript" src="ext-all.js" charset="gb2312"></script>


<script type="text/javascript" src="array-grid.js" charset="gb2312"></script>


<link rel="stylesheet" type="text/css" href="grid-examples.css" />

<link rel="stylesheet" type="text/css" href="shared/examples.css" />


<script type="text/javascript" src="shared/examples.js" charset="gb2312"></script>

</head>

<body>

<form id="form1" runat="server">

<div>

<h1>

extjs+wcf+linq 打造grid</h1>

<div id="grid-example">

</div>

</div>

</form>

</body>

</html>


页面中有对<script type="text/javascript" src="array-grid.js" charset="gb2312"></script>,其中的array-grid.js便是产生grid所需要的脚本,它访问上一步中开发好的wcf服务,将服务方法GetStocks返回的json数据与extjs的grid进行绑定,具体代码如下:

ExtJs与Wcf交互生成grid的脚本代码

/**//**//**//*

* Ext JS Library 2.1

* Copyright(c) 2006-2008, Ext JS, LLC.

* licensing@extjs.com

*

* http://extjs.com/license

*/



Ext.onReady(function()
{


// example of custom renderer function


function change(val)
{


if(val > 0)
{

return '<span style="color:green;">' + val + '</span>';


}else if(val < 0)
{

return '<span style="color:red;">' + val + '</span>';

}

return val;

}


// example of custom renderer function


function pctChange(val)
{


if(val > 0)
{

return '<span style="color:green;">' + val + '%</span>';


}else if(val < 0)
{

return '<span style="color:red;">' + val + '%</span>';

}

return val;

}


var proxy=new Ext.data.HttpProxy(
{url:'ArrayGridService.svc/GetStocks'});


// create the data store


var store = new Ext.data.SimpleStore(
{

fields: [



{name: 'company'},



{name: 'price', type: 'float'},



{name: 'change', type: 'float'},



{name: 'pctChange', type: 'float'},



{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}

]

});



//定义reader

var reader=new Ext.data.JsonReader(



{

},[



{name: 'company'},



{name: 'price'},



{name: 'change'},



{name: 'pctChange',mapping:'changepercent'},



{name: 'lastChange',mapping:'lastupdated'}

]

)

//构建Store


var store=new Ext.data.Store(
{

proxy:proxy,

reader:reader

});

//载入

store.load();



// create the Grid


var grid = new Ext.grid.GridPanel(
{

store: store,

columns: [



{id:'company',header: "公司", width: 160, sortable: true, dataIndex: 'company'},



{header: "单价", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},



{header: "变动", width: 75, sortable: true, renderer: change, dataIndex: 'change'},



{header: "变动百分比", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},



{header: "最后更新", width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('Y年m月d日'), dataIndex: 'lastChange'}

],

stripeRows: true,

autoExpandColumn: 'company',

height:350,

width:600,

title:'股市行情',

viewConfig:



{

columnsText:'列',

sortAscText:'升序',

sortDescText:'降序'

}

});


grid.render('grid-example');


grid.getSelectionModel().selectFirstRow();

});


到此,linq部分,wcf部分,extjs部分均开发完成。
第五步:在浏览器中浏览BasicGrid.aspx,效果图如下:
说明大功告成。
说明:这几篇都是简单的实践,有关extjs部分绝大部分参考extjs中的示例,但也做了稍稍的修改,后面的文章会逐渐深入一些。
示例项目:
/Files/jillzhang/ExtJsWcfLinqGrid.part1.RAR
/Files/jillzhang/ExtJsWcfLinqGrid.part2.RAR
posted @ 2008-06-18 22:16
Robin Zhang 阅读(5165)
评论(42) 编辑 收藏 网摘 所属分类:
ajaxweb serviceWCF
发表评论
很好的文章,国内关于ExtJS与WCF的交互大多都是互相抄袭。所以有自己的探讨并且写文章让大家分享讨论,不错!!不过我个人感觉,脚本代码和连接支持等似乎没必要放入aspx文件,为什么不使用静态文件呢?ExtJs就前台显示而言,仅仅用静态文件就可以了,不知道这样做效率会否更高?
Ext的功能很不错,与ASP.NET MVC组合也可以取得很好的效果。
#8楼[
楼主]2008-06-19 09:12 |
@哦,奇怪
多谢支持
@Anytao
王兄来捧场,我特高兴
@U2U
国内关于ExtJS与WCF的交互大多都是互相抄袭
---------------------------------
实不相瞒,我这篇也是参考了ExtJs示例项目和其他人的,可能更加详细一点,该注意的地方注明了一下。作为敲门砖式的文章,我会尽量开始简单一些,多参考文档和别人的示例,以后会逐渐加入自己的东西,也是一种学习过程嘛。
@高海东
@戏水
------------------------------
哈哈,多谢啦
@阿不
你的想法,我觉得可以尝试尝试,现在我感觉比起webform来,extjs+wcf更爽了。
而且extjs支持html,页面与代码逻辑分离的更彻底一些
#10楼[
楼主]2008-06-19 09:16 |
@Jeffrey Zhao
太大了,容易撑开页面,呵呵:)
#11楼[
楼主]2008-06-19 09:18 |
@yaoliping
直接访问.svc会出现没有找到终结点
访问.svc/GetStocks就可以了
#13楼[
楼主]2008-06-19 10:21 |
@yaoliping
你的iis支持svc后缀么?
没有配置过svc支持,要先配置
楼主:对类添加DataContractAttribute,对属性添加DataMemberAttribute
好像代码上面没有体现。。请指点
我用VS2008自带的ASP.NET DEVELOPMENT SEVER运行LZ的程序时,和@yaoliping 的一样,通过附加进程调试时,ArrayGridService.cs代码,方法 public Stock[] GetStocks() 显示有七条记录,说明是正确的.但是
在JS文件array-grid.js 代码store.load();添加
alert('记录数:'+store.getCount());
显示为: 记录数:0
@dada7357
楼主没有在类上添加DataContractAttribute,对属性添加DataMemberAttribute ,所以没有被序列化,客户端就没有内容啦
--引用--------------------------------------------------
Ants: @dada7357
楼主没有在类上添加DataContractAttribute,对属性添加DataMemberAttribute ,所以没有被序列化,客户端就没有内容啦
--------------------------------------------------------
不行,我加了DataContractAttribute,DataMemberAttribute 也没有数据!
#18楼[
楼主]2008-06-19 12:08 |
@yaoliping
不要用虚拟目录,用网站
#19楼[
楼主]2008-06-19 12:11 |
@Ants
楼主没有在类上添加DataContractAttribute,对属性添加DataMemberAttribute ,所以没有被序列化,客户端就没有内容啦
--------------------------------------------------------
不好意思,我原来的类是加了的,可能代码拷贝错了。
DataContract和DataMember是要加的
用文件形式打开和网站打开项目都可以运行,结果也能出来!就是需要加上DataContract和DataMember!感谢楼主无私奉献!期待下文!
#22楼[
楼主]2008-06-29 07:39 |
@知秋一叶
多谢支持
我浏览的时候,“最后更新”显示为NaN年NaN月NaN日,这是什么原因引起的呢
我发现WCF返回的JSON的数据为:
[{"company":"3m Co","price":71.72,"change":0.02,"changepercent":0.03,"lastupdated":"\/Date(1213718400000+0800)\/"},
{"company":"Alcoa Inc","price":29.01,"change":0.01,"changepercent":0.02,"lastupdated":"\/Date(1213718400000+0800)\/"},
{"company":"Altria Group Inc","price":85.03,"change":-0.02,"changepercent":-0.03,"lastupdated":"\/Date(1150473600000+0800)\/"},
{"company":"American Express Company","price":85.3,"change":0.32,"changepercent":0.12,"lastupdated":"\/Date(1213718400000+0800)\/"},
{"company":"American International Group, Inc.","price":64.12,"change":-0.01,"changepercent":-0.01,"lastupdated":"\/Date(1213718400000+0800)\/"},
{"company":"AT&T Inc.","price":52.36,"change":0.1,"changepercent":0.05,"lastupdated":"\/Date(1213718400000+0800)\/"},
{"company":"Boeing Co.","price":56.36,"change":-0.02,"changepercent":-0.01,"lastupdated":"\/Date(1213545600000+0800)\/"}]
发现日期,"lastupdated":"\/Date(1213545600000+0800)\/"的格式与EXTJS不适配,请问有什么办法可以解决吗?
#25楼[
楼主]2008-08-24 09:11 |
@XDS
我做的时候,也遇到了同样的问题
我将服务端数据契约的DateTime更改为string就可以了
@菩提树下的杨过
可以解决从WCF到Extjs的问题。但日期型字段(如:该例子中的最后最新时间)一旦编辑后就会出现错误。错误的原因在于render解析的错误。因为Extjs的日期控件生成的是标准的日期格式如(2008-09-02)而解析器是解析UTC格式,当然可以将解析器同时支持多种格式。但还有一个问题:如何将编辑完成的日期以UTC格式(即WCF生成的日期格式)传回WCF进行更新。
@XDS
这个到是没试过,不过WCF的方法,好象可以分别设置Request和Response的格式,可以试下把Request设置为xml,Response设置为json,不知可行否?
{header: "变动", width: 75, sortable: true, renderer: change, dataIndex: 'change'},
这个 renderer: change 是控制什么属性的?
#30楼[
楼主]2008-09-08 09:28 |
@菩提树下的杨过
将DateTime更改为String就可以交互了
#31楼[
楼主]2008-09-08 09:31 |
@junelee1211
render是一个类似于委托的东西
付给他的也是一个函数的名称,在显示数据的时候,会调用这个函数对元数据就行处理,比如格式化,从而个性显示,比如原始数据存储为0,1代表男女,可以写一个方法function,将0,1显示为男女。render就完成这样的功能
对类添加DataContractAttribute,对属性添加DataMemberAttribute
请问这步具体怎么操作啊,我每项都是一点点跟着做的,但就是WCF服务不传出数据来,可能就是这没有设置。
#33楼[
楼主]2008-09-10 08:59 |
@flygod
wcf有传出数据,我认为你看到的可能和实际有些不符
也可能是已经传出数据了,但因为你的extjs设置有问题,所以没有显示出来
对linq生成的类添加DataContract,属性添加DataMember是非常简单的
不是的,在调式程序的时候,我使用了IE封包数据查看工具,返回LINQ生成的数组的时候,WCF就是空返回值,但如果我改成返回字符串的时候,就会返回正确值,我怀疑是不是LINQ的那个地方没有设置对,它的查询出来的值不能让WCF正常调用的原因.
在VS2008的调式中,我设置了断点,可以看到return res.ToArray<Stock>(); RES数组的内容是正确的,就是不能通过WCF发送给客户端.
而且"对linq生成的类添加DataContract,属性添加DataMember"这个设置我一直没有找到地方,是手动写代码,还是在面板中设置呢?
在页面文件中,在<%@ ServiceHost中添加Factory="System.ServiceModel.Activation.WebServiceHostFactory",然后在web.config中将<enableWebScript/>替换成为<webHttp/>,注意这两个操作是必须的。到此wcf服务也准备齐备。
------------------------------------------------------------------
楼主应该说明下.这两个这样改是为啥?突然冒出这两个怪怪的,上一篇已经出现过.呵呵.还没有翻MSDN哈
你的iis支持svc后缀么?
没有配置过svc支持,要先配置
怎么配置svc支持啊 .net iss 不太熟悉
楼上同学,iis要支持svc后缀要安装一个xx.在.net framework目录下.好像是3.5还是那个.忘记了.你搜索下吧.博客园里面有
#38楼[
楼主]2008-11-22 12:30 |
@mark_xu
iis 6.0支持svc需要安装.net framework 3.X
另外需要添加对svc的映射
(ExtJs+WCF+LINQ实现分页Grid )照着你的方式做了下 returnData 返回的数据都是正确的 但是我的grid就是没有显示数据啊
怎么回事啊?急待楼主解答 谢谢!
var proxy=new Ext.data.HttpProxy( {url:'WcfJsonService.svc/GetTeacherInfoProfile'});
var store = new Ext.data.SimpleStore({fields: [ {name: 'ID',type:'int'}, {name: 'TeacherNodeID', type: 'long'}, {name: 'PublicTel', type: 'string'}, {name: 'PublicFax', type: 'string'}, {name: 'RecordTime', type: 'date'}]});
var reader=new Ext.data.JsonReader({ },[ {name: 'ID',type:'int'}, {name: 'TeacherNodeID', type: 'long'}, {name: 'PublicTel', type: 'string'}, {name: 'PublicFax', type: 'string'}, {name: 'RecordTime', type: 'date'}] );
store=new Ext.data.Store( { proxy:proxy, reader:reader });
store.load();
var grid = new Ext.grid.GridPanel({store: store, columns: [ {id:'ID',header: "序号", width: 160, sortable: true, dataIndex: 'ID'}, {header: "教师", width: 75, sortable: true, dataIndex: 'TeacherNodeID'}, {header: "显示电话", width: 75, sortable: true, dataIndex: 'PublicTel'}, {header: "显示传真", width: 75, sortable: true,dataIndex: 'PublicFax'}, {header: "时间", width: 75, sortable: true, dataIndex: 'RecordTime'}],stripeRows: true,autoExpandColumn: 'ID', height:350, width:600, title:'教师列表', viewConfig:{ columnsText:'列', sortAscText:'升序', sortDescText:'降序' } });
我也是比着写的,不能正确显示数据。郁闷了一天了!!
终于搞出来了,谢谢,{name: 'TeacherNodeID', type: 'long'}换成{name: 'TeacherNodeID', type: 'float'},就可以了。
兄弟 我请教一下! 先谢了!
在 EXTJS里能动态实现类似于这样的表头格式吗??动态的静态的都可以!!最好是动态的!能否给小弟提供一些信息!! 急!! 拜托胜兄了!!!
