Extjs4 跨域调用WCF

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: "标题",  120, dataIndex: 'title', sortable: true},
            {text: "作者", flex: 200, dataIndex: 'author', sortable: false},
            {text: "点击数",  100, dataIndex: 'hits', sortable: true},
            {text: "添加时间",  100, dataIndex: 'addtime', sortable: true}
        ],
        height:400,
        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即可。

运行界面如下:

初始化时

image 

换页时

image

5. 总结

Extjs部分没有什么特别的地方,主要是WCF部分有以下几点需要注意:

  1. 对于被跨域调用的契约方法,加上[WebGet]atrribute
  2. 对于被跨域调用的实际类,加上[AspNetCompatibilityRequirements]atrribute
  3. 对于被跨域调用的服务,配置中必须使用webHttpBinding方式,basicHttpBinding不行。
  4. 对于被跨域调用的服务,配置中需要关联enableWebScript的behavior。

总体感觉比较麻烦,如果有好的方法,欢迎指出!!

原文地址:https://www.cnblogs.com/wang_yb/p/2160139.html