ExtJs与WCF之间的跨域访问

本文详细介绍了使用ExtJS与WCF实现跨域分页Grid的复杂过程,包括创建代理页面Proxy.aspx以绕过跨域限制,以及调整ExtJS脚本和WCF服务端代码的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇文章<<ExtJs+WCF+LINQ实现分页Grid>>中用ExtJs与Wcf交互实现了分页Grid,回复中心有灵犀同学希望能采用跨域访问的方式,这个问题其实也困扰了我很久,本来ExtJS用ScriptTagProxy支持跨域访问的,如果服务端是.aspx的页面文件,也非常好实现,但换作WCF,问题就复杂起来。本文尝试解决这个问题,方案不是很巧妙,但是我对多种方案实验中第一个且是唯一有效的办法。

首先看一下如何用ExtJs中的ScriptTagProxy跨域访问服务器.aspx页面,不是重点,但与为何此种方法不适用WCF相关,所以也赘述下,项目是上文中的项目,下面是实现步骤:

第一步:还是向网站中添加Service.aspx页面,然后将其代码更改如下:

Service.aspx代码
using System; 

using System.Collections; 

using System.Configuration; 

using System.Data; 

using System.Linq; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.HtmlControls; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Xml.Linq; 

 

namespace ExtJs_Wcf_Linq_PageGrid 



public partial class Service : System.Web.UI.Page 



protected void Page_Load(object sender, EventArgs e) 



int start = Convert.ToInt32(Request.QueryString["start"]); 

int limit = Convert.ToInt32(Request.QueryString["limit"]); 

string callback = Request.QueryString["callback"]; 

ProductsDataContext productDbContext 
= new ProductsDataContext(); 

IQueryable
<Product> res = productDbContext.Product.Select(product => product); 

PageData
<Product[]> returnData = new PageData<Product[]>(); 

returnData.TotolRecord 
= res.ToArray<Product>().Length; 

res 
= res.Skip<Product>(start); 

res 
= res.Take<Product>(limit); 

returnData.Data 
= res.ToArray<Product>(); 

System.Runtime.Serialization.Json.DataContractJsonSerializer serializer 
= new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(PageData<Product[]>)); 

 

using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) 



serializer.WriteObject(ms, returnData); 

ms.Position 
= 0

System.IO.StreamReader sr 
= new System.IO.StreamReader(ms); 

Response.Write(callback
+"("+sr.ReadToEnd()+")"); 

}
 

}
 

}
 

}
 

第二步:创建一个htm页面PageGridCrossDomain.htm然后将其代码更改为:

PageGridCrossDomain.htm
<!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> 

<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-debug.js" charset="gb2312"></script> 

 

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

 

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

 

<script src="ScriptTagReader.js" type="text/javascript"></script> 

 

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

 

</head> 

<body> 

<h1> 

ExtJs+WCF+LINQ打造分页跨域Grid
</h1> 

<div id="page-grid"> 

</div> 

</body> 

</html> 

 第三步:添加实现跨域分页的脚本文件

PageCrossDomain.js
/**//* 

* Ext JS Library 2.1 

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

* licensing@extjs.com 



* http://extjs.com/license 

*/
 

Ext.onReady(
function()

 

//创建一个用于访问WCF服务的HttpProxy,且访问方法为GET 

var proxy = new Ext.data.ScriptTagProxy(

url:
'http://127.0.0.1:50643/Service.aspx' 

}
); 

 

var reader = new Ext.data.JsonReader( 

{root:'Data',totalProperty :'TotolRecord'}



{name: 'ProductID'}

{name: 'Name'}

{name: 'ProductNumber'}

{name: 'MakeFlag'}

{name: 'FinishedGoodsFlag'}

{name: 'Color'}

{name: 'SafetyStockLevel'}

{name: 'ReorderPoint'}

{name: 'StandardCost'}

{name: 'ListPrice'}

{name: 'Size'}

{name: 'SizeUnitMeasureCode'}

{name: 'Weight'}

{name: 'DaysToManufacture'}

{name: 'ProductLine'}

{name: 'Class'}

{name: 'Style'}

{name: 'Weight'}

{name: 'ProductSubcategoryID'}

{name: 'ProductModelID'}

{name: 'SellStartDate'}

{name: 'SellEndDate'}

{name: 'DiscontinuedDate'}

{name: 'rowguid'}

{name: 'ModifiedDate'} 



); 

 

var store = new Ext.data.Store( 

{proxy:proxy,reader:reader} 

); 

 

// create the Grid 

var grid = new Ext.grid.GridPanel(

store: store, 

columns: [ 

{id:'ProductID',header: "编号",width:30, sortable: true, dataIndex: 'ProductID'}

{header: "名称", width:75, sortable: true, dataIndex: 'Name'}

{header: "产品编码", width:75, sortable: true, dataIndex: 'ProductNumber'}

{header: "是否标记", width:75, sortable: true, dataIndex: 'MakeFlag'}

{header: "颜色", width:50, sortable: true,dataIndex:'Color'}

{header: "数量", width:50, sortable: true,dataIndex:'ReorderPoint'}

{header: "单价", width:50, sortable: true,renderer:'userMoney',dataIndex: 'StandardCost'} 

], 

stripeRows: 
true

autoExpandColumn: 
'ProductID'

height:
400

width:
600

title:
'产品信息'

viewConfig: 



columnsText:
''

sortAscText:
'升序'

sortDescText:
'降序' 

}


bbar: 
new Ext.PagingToolbar(

pageSize: 
25

store: store, 

displayInfo: 
true

displayMsg: 
'总记录数 {0} - {1} of {2}'

emptyMsg: 
"没有记录" 

}


}
); 

 

grid.render(
'page-grid'); 

 

//载入 

store.load(
{params:{start:0,limit:25}}); 

 

grid.getSelectionModel().selectFirstRow(); 

}
); 

浏览PageGridCrossDomain.htm,效果图如下:

好,到此用ExtJs跨域调用.aspx的示例已经完成,过程相当简单,效果也比较完美。

但我写此系列的文章,主要目的在于探讨ExtJs与Wcf交互,经过前面几篇的学习,已经对WCF的RestFul和ExtJs的使用有了些皮毛认识,深切体会到ExtJs+Wcf是一种比较不错的编程模型,它与传统的B/S,C/S都不太一样,相比WebForm,它更像是web开发。而且服务的概念也会得以深刻体现,可谓一箭双雕。书写本文之前,我尝试了很多种办法用于ExtJs跨域访问Wcf实现分页Grid,但都没有成功,查阅了ScriptTagProxy的源码方才发现一些端倪,原来ScriptTagProxy是通过动态创建<scipt>的方式实现跨域的,原理可见阿布 的一篇文章:利用script标签实现的跨域名AJAX请求(ExtJS),我也不再赘述,下面给出ScriptTagProxy源码中的一个片段:

这段代码中的 url便是要跨域访问的地址,由此可见url返回的信息必须是完全符合<script></script>格式要求的代码,否则将出现javascript错误,我在前期用ScriptTagProxy调用WCF,总是出现莫名错误,便是缘于此。WCF能返回JSON格式的数据,但这样的数据是不符合变量声明要求的,而察看extjs示例中跨域的相应格式为: strCallback1001({..json数据…}),这样一种格式是声明了一个对象变量strCallback1001,而再看看我们可爱的WCF呢,当我们将其ResponseFormat = WebMessageFormat.Json,而返回PageData<Product[]>,他返回的标准的json数据,不符合要求,而返回string,去掉ResponseFormat = WebMessageFormat.Json,然后在服务方法体中用类似Service.aspx得到json数据的办法得到json数据,然后再通过字符串拼接成js变量声明符合格式要求的数据的时候,再看返回,这次可好,前面无缘无故的给WCF加上了<xml . Type="string">,原来WCF只支持良种编码格式:XML,Json,这时候我就晕了,你说WCF要是支持个ClearText编码格式,那问题不就解决了嘛,唉,没办法,看来想用ScriptTagProxy是不行了。这个问题困扰了我几天。其实此处我觉得WCF是应该有返回ClearText的选项的,不管怎么样,那样更灵活。可没办法,我查了个遍,认识的几个大牛,也问了,都没有确定答案。

上面一段是一些牢骚,既然是牢骚,语法与思路自然有些乱了,但基本上应该说明了ExtJs与WCF跨域交互的障碍了。

下面是我扫除这一障碍的一个笨得不能再笨的方法

第一步:在项目中创建一个页面Proxy.aspx,作为ExtJs与Wcf跨域操作的代理页面。这个页面和ExtJs位于一个位置,并且去除页面中的HTML代码:

后台代码为:

Proxy.aspx.cs
using System; 

using System.Collections; 

using System.Configuration; 

using System.Data; 

using System.Linq; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.HtmlControls; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Xml.Linq; 

using System.Collections.Specialized; 

 

namespace ExtJs_Wcf_Linq_PageGrid 



public partial class Proxy : System.Web.UI.Page 



protected void Page_Load(object sender, EventArgs e) 



string remoteUrl = Request.QueryString["remote"]; 

using(System.Net.WebClient wc = new System.Net.WebClient()) 



NameValueCollection nvc 
= Request.QueryString; 

foreach (string key in nvc.Keys) 



if (key != "remote"



if (remoteUrl.IndexOf("?"== -1



remoteUrl 
= remoteUrl + "?"+key+"="+ nvc[key]; 

continue

}
 

remoteUrl 
= remoteUrl + "&" + key + "=" + nvc[key]; 

}
 

}
 

string response = wc.DownloadString(remoteUrl); 

Response.Write(response); 

Response.End(); 

}
 

}
 

}
 

}
 

第二步:创建一个ExtJs通过服务代理与Wcf实现跨域交互的htm页面 :PageGridCrossDomainWcf.htm

PageGridCrossDomainWcf.htm
<!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> 

<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-debug.js" charset="gb2312"></script> 

 

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

 

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

 

<script src="ScriptTagReader.js" type="text/javascript"></script> 

 

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

 

</head> 

<body> 

<h1> 

ExtJs+WCF+LINQ打造分页跨域Grid
</h1> 

<div id="page-grid"> 

</div> 

</body> 

</html> 

第三步:创建用于ExtJs与Wcf跨域交互的脚本文件:PageGridCrossDoaminWcf.js

PageGridCrossDoaminWcf.js
/**//* 

* Ext JS Library 2.1 

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

* licensing@extjs.com 



* http://extjs.com/license 

*/ 

Ext.onReady(
function()

 

//创建一个用于访问WCF服务的HttpProxy,且访问方法为GET 

var proxy = new Ext.data.HttpProxy(

url:
'Proxy.aspx?remote=http://127.0.0.1:50643/PageGridService.svc/GetProductsByPage'

method:
'GET' 

}
); 

 

var reader = new Ext.data.JsonReader( 

{root:'Data',totalProperty :'TotolRecord'}



{name: 'ProductID'}

{name: 'Name'}

{name: 'ProductNumber'}

{name: 'MakeFlag'}

{name: 'FinishedGoodsFlag'}

{name: 'Color'}

{name: 'SafetyStockLevel'}

{name: 'ReorderPoint'}

{name: 'StandardCost'}

{name: 'ListPrice'}

{name: 'Size'}

{name: 'SizeUnitMeasureCode'}

{name: 'Weight'}

{name: 'DaysToManufacture'}

{name: 'ProductLine'}

{name: 'Class'}

{name: 'Style'}

{name: 'Weight'}

{name: 'ProductSubcategoryID'}

{name: 'ProductModelID'}

{name: 'SellStartDate'}

{name: 'SellEndDate'}

{name: 'DiscontinuedDate'}

{name: 'rowguid'}

{name: 'ModifiedDate'} 



); 

 

var store = new Ext.data.Store( 

{proxy:proxy,reader:reader} 

); 

 

// create the Grid 

var grid = new Ext.grid.GridPanel(

store: store, 

columns: [ 

{id:'ProductID',header: "编号",width:30, sortable: true, dataIndex: 'ProductID'}

{header: "名称", width:75, sortable: true, dataIndex: 'Name'}

{header: "产品编码", width:75, sortable: true, dataIndex: 'ProductNumber'}

{header: "是否标记", width:75, sortable: true, dataIndex: 'MakeFlag'}

{header: "颜色", width:50, sortable: true,dataIndex:'Color'}

{header: "数量", width:50, sortable: true,dataIndex:'ReorderPoint'}

{header: "单价", width:50, sortable: true,renderer:'userMoney',dataIndex: 'StandardCost'} 

], 

stripeRows: 
true

autoExpandColumn: 
'ProductID'

height:
400

width:
600

title:
'产品信息'

viewConfig: 



columnsText:
''

sortAscText:
'升序'

sortDescText:
'降序' 

}


bbar: 
new Ext.PagingToolbar(

pageSize: 
25

store: store, 

displayInfo: 
true

displayMsg: 
'总记录数 {0} - {1} of {2}'

emptyMsg: 
"没有记录" 

}


}
); 

 

grid.render(
'page-grid'); 

 

//载入 

store.load(
{params:{start:0,limit:25}}); 

 

grid.getSelectionModel().selectFirstRow(); 

}
); 

好了,现在浏览PageGridCrossDomainWcf.htm,效果图如下:

最后,国际惯例,代码示例:

< p>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值