上篇文章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 阅读(7883)
评论(48) 编辑 收藏
发表评论
很好的文章,国内关于ExtJS与WCF的交互大多都是互相抄袭。所以有自己的探讨并且写文章让大家分享讨论,不错!!不过我个人感觉,脚本代码和连接支持等似乎没必要放入aspx文件,为什么不使用静态文件呢?ExtJs就前台显示而言,仅仅用静态文件就可以了,不知道这样做效率会否更高?
Ext的功能很不错,与ASP.NET MVC组合也可以取得很好的效果。
@哦,奇怪
多谢支持
@Anytao
王兄来捧场,我特高兴
@U2U
国内关于ExtJS与WCF的交互大多都是互相抄袭
---------------------------------
实不相瞒,我这篇也是参考了ExtJs示例项目和其他人的,可能更加详细一点,该注意的地方注明了一下。作为敲门砖式的文章,我会尽量开始简单一些,多参考文档和别人的示例,以后会逐渐加入自己的东西,也是一种学习过程嘛。
@高海东
@戏水
------------------------------
哈哈,多谢啦
@阿不
你的想法,我觉得可以尝试尝试,现在我感觉比起webform来,extjs+wcf更爽了。
而且extjs支持html,页面与代码逻辑分离的更彻底一些
@Jeffrey Zhao
太大了,容易撑开页面,呵呵:)
@yaoliping
直接访问.svc会出现没有找到终结点
访问.svc/GetStocks就可以了
@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 也没有数据!
@Ants
楼主没有在类上添加DataContractAttribute,对属性添加DataMemberAttribute ,所以没有被序列化,客户端就没有内容啦
--------------------------------------------------------
不好意思,我原来的类是加了的,可能代码拷贝错了。
DataContract和DataMember是要加的
用文件形式打开和网站打开项目都可以运行,结果也能出来!就是需要加上DataContract和DataMember!感谢楼主无私奉献!期待下文!
我浏览的时候,“最后更新”显示为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不适配,请问有什么办法可以解决吗?
@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 是控制什么属性的?
@菩提树下的杨过
将DateTime更改为String就可以交互了
@junelee1211
render是一个类似于委托的东西
付给他的也是一个函数的名称,在显示数据的时候,会调用这个函数对元数据就行处理,比如格式化,从而个性显示,比如原始数据存储为0,1代表男女,可以写一个方法function,将0,1显示为男女。render就完成这样的功能
对类添加DataContractAttribute,对属性添加DataMemberAttribute
请问这步具体怎么操作啊,我每项都是一点点跟着做的,但就是WCF服务不传出数据来,可能就是这没有设置。
@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还是那个.忘记了.你搜索下吧.博客园里面有
@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里能动态实现类似于这样的表头格式吗??动态的静态的都可以!!最好是动态的!能否给小弟提供一些信息!! 急!! 拜托胜兄了!!!

真的讲的蛮到位的,没接触过wcf的我,一下子就看懂了,本来不想回复的,最后还是决定登录后来回复支持一下,谢谢。
您好 同样的问题 为什么我吧您的数据库也附件了 数据库的密码也设置的没问题,为什么又是不加载数据呢? 请求支援
老师,你好!
部署在IIS上户出现如下错误:
请问怎么搞啊
联系邮箱:markmao_love@126.com
谢谢
“/TestDemoWeb”应用程序中的服务器错误。
--------------------------------------------------------------------------------
IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used.
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.InvalidOperationException: IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used.
源错误:
执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。
堆栈跟踪:
[InvalidOperationException: IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used.]
System.ServiceModel.Web.WebServiceHost.SetBindingCredentialBasedOnHostedEnvironment(ServiceEndpoint serviceEndpoint, AuthenticationSchemes supportedSchemes) +446264
System.ServiceModel.Web.WebServiceHost.AddAutomaticWebHttpBindingEndpoints(ServiceHost host, IDictionary`2 implementedContracts, String multipleContractsErrorMessage) +709
System.ServiceModel.Web.WebServiceHost.OnOpening() +203
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +229
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +121
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +479
[ServiceActivationException: The service '/TestDemoWeb/ArrayGridService.svc' cannot be activated due to an exception during compilation. The exception message is: IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used..]
System.ServiceModel.AsyncResult.End(IAsyncResult result) +11599786
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +194
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +176
System.ServiceModel.Activation.HttpHandler.ProcessRequest(HttpContext context) +23
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
--------------------------------------------------------------------------------
版本信息: Microsoft .NET Framework 版本:2.0.50727.3615; ASP.NET 版本:2.0.50727.3618
@U2U
嘿嘿 和我想法一样
不过目前做法是把不用的 引用全部删掉
vs有方法的