Javascript跨域调用的问题折腾了我好几天,主要参考了博客园大牛jillzhang的两篇博客
博客中没有提供工程源码下载,我把其中的代码拷下来运行,extjs部分始终取不到数据。
可能Extjs4和WCF都有了一些变化,而这两篇博客比较老,所以运行不了。
经过一些修改(主要是加了WCF配置文件的部分),终于可以运行下面这个Grid分页的例子了。
1. Extjs4 部分的代码
主要有2部分:一部分是html,一部分是js
html部分代码
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Paging Grid-MHZG.NET</title>
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
<script type="text/javascript" src="extjs/bootstrap.js"></script>
<script type="text/javascript" src="extjs/ext-all.js"></script>
<script type="text/javascript" src="extjs/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript" src="paging.js"></script>
</head>
<body>
<div id="demo"></div>
</body>
</html>
js部分代码,即paging.js的代码。其他js和css文件是Ext框架自带的。
Ext.require([
'Ext.grid.*',
'Ext.toolbar.Paging',
'Ext.data.*'
]);
Ext.onReady(function(){
Ext.define('MyData',{
extend: 'Ext.data.Model',
fields: [
'title','author',
//第一个字段需要指定mapping,其他字段,可以省略掉。
{name:'hits',type: 'int'},
'addtime'
]
});
//创建数据源
var store = Ext.create('Ext.data.Store', {
//分页大小
pageSize: 50,
model: 'MyData',
//是否在服务端排序
remoteSort: true,
proxy: {
type: 'jsonp',
url: 'http://localhost:4124/Service1.svc/Paging',
reader: {
root: 'items',
totalProperty : 'total'
},
simpleSortMode: true
},
sorters: [{
//排序字段。
property: 'hits',
//排序类型,默认为 ASC
direction: 'DESC'
}]
});
//创建Grid
var grid = Ext.create('Ext.grid.Panel',{
store: store,
columns: [
{text: "标题", width: 120, dataIndex: 'title', sortable: true},
{text: "作者", flex: 200, dataIndex: 'author', sortable: false},
{text: "点击数", width: 100, dataIndex: 'hits', sortable: true},
{text: "添加时间", width: 100, dataIndex: 'addtime', sortable: true}
],
height:400,
width:520,
x:20,
y:40,
title: 'ExtJS4 Grid 分页示例',
disableSelection: true,
loadMask: true,
renderTo: 'demo',
viewConfig: {
id: 'gv',
trackOver: false,
stripeRows: false
},
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
displayMsg: '显示 {0} - {1} 条,共计 {2} 条',
emptyMsg: "没有数据"
})
})
store.loadPage(1);
})
其中关键部分即:
proxy: {
type: 'jsonp',
url: 'http://localhost:4124/Service1.svc/Paging',
type设为jsonp,则使用的Ext.data.ScriptTagProxy这个代理。
url为全路径,表示可以跨域调用。
2. WCF代码部分
Service1.svc
<%@ ServiceHost Language="C#" Debug="true" Service="Service1" CodeBehind="Service1.svc.cs" %>
Service1.svc.cs
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO;
using System.ServiceModel.Activation;
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1:IService1
{
public Stream Paging(string _dc, int start, int limit, int page, string callback)
{
StringBuilder sb = new StringBuilder();
sb.Append("{'total':1000, 'items': [ ");
for (int i = start; i < start+limit - 1; i++)
{
sb.Append("{ 'title': ").Append("'title").Append(i).Append("',");
sb.Append(" 'author': ").Append("'author").Append(i).Append("',");
sb.Append(" 'hits': ").Append(i).Append(",");
sb.Append(" 'addtime':'2011/1/1'}, ");
}
sb.Append("{ 'title': ").Append("'title").Append(start + limit).Append("',");
sb.Append(" 'author': ").Append("'author").Append(start + limit).Append("',");
sb.Append(" 'hits': ").Append(start + limit).Append(",");
sb.Append(" 'addtime':'2011/1/1'} ");
sb.Append("] }");
string returnStr = callback + "(" + sb.ToString() + ")";
var ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
sw.AutoFlush = true;
sw.Write(returnStr);
ms.Position = 0;
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return ms;
}
}
[ServiceContract(Namespace = "")]
public interface IService1
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
Stream Paging(string _dc, int start, int limit, int page, string callback);
}
3. WCF配置部分,即Web.config中system.serviceModel部分
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonServiceBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="Service1">
<endpoint binding="webHttpBinding" contract="IService1" behaviorConfiguration="jsonServiceBehavior"/>
</service>
</services>
</system.serviceModel>
4. 运行效果
启动上面的WCF服务,根据实际的端口号修改Extjs部分的url,然后打开Extjs部分的html即可。
运行界面如下:
初始化时
换页时
5. 总结
Extjs部分没有什么特别的地方,主要是WCF部分有以下几点需要注意:
- 对于被跨域调用的契约方法,加上[WebGet]atrribute
- 对于被跨域调用的实际类,加上[AspNetCompatibilityRequirements]atrribute
- 对于被跨域调用的服务,配置中必须使用webHttpBinding方式,basicHttpBinding不行。
- 对于被跨域调用的服务,配置中需要关联enableWebScript的behavior。
总体感觉比较麻烦,如果有好的方法,欢迎指出!!