一个通过JSONP跨域调用WCF REST服务的例子(以jQuery为例)

JSONP(JSON with Padding)可以看成是JSON的一种“使用模式”,用以解决“跨域访问”的问题,这篇简单的文章给出一个简单的例子用于模拟如何通过jQuery以JSONP的访问调用一个WCF REST服务。[源代码从这里下载]

在这个例子中,我们将定义一个用于返回所有员工信息的服务,下面是用于表示员工信息的Employee的类型和契约接口。契约接口IEmployees的GetAll操作用以返回所有员工列表,我们指定了Uri模板并将回复消息格式设置为JSON。

   1: using System.Collections.Generic;
   2: using System.ServiceModel;
   3: using System.ServiceModel.Web;
   4: namespace Artech.WcfServices.Service.Interface
   5: {
   6:     [ServiceContract]
   7:     public interface IEmployees
   8:     {
   9:         [WebGet(UriTemplate = "all",ResponseFormat =WebMessageFormat.Json)]      
  10:         IEnumerable<Employee> GetAll();
  11:     }
  12:     public class Employee
  13:     {
  14:         public string Id { get; set; }
  15:         public string Name { get; set; }
  16:         public string Department { get; set; }
  17:         public string Grade { get; set; }
  18:     }
  19: }

在如下所示的服务类型EmployeesService 中,我们直接让服务操作GetAll返回一个包含3个Employee对象的列表。

   1: using System.Collections.Generic;
   2: using Artech.WcfServices.Service.Interface;
   3: namespace Artech.WcfServices.Service
   4: {
   5:     public class EmployeesService : IEmployees
   6:     {
   7:         public IEnumerable<Employee> GetAll()
   8:         {
   9:             return new List<Employee>
  10:             {
  11:                 new Employee{ Id = "001", Name="张三", Department="开发部", Grade = "G6"},    
  12:                 new Employee{ Id = "002", Name="李四", Department="人事部", Grade = "G7"}, 
  13:                 new Employee{ Id = "003", Name="王五", Department="销售部", Grade = "G8"}
  14:             };
  15:         }
  16:     }
  17: }

我们通过控制台程序对服务进行寄宿。从下面的配置可以看到我们采用了标准终结点WebHttpEndpoint。为了让服务具有跨域支持的能力,我们必须将标准终结点的crossDomainScriptAccessEnabled属性设置为True。WebHttpBinding也具有同名的属性,如果直接使用WebHttpBinding也需要将该属性设置为True。

   1: <configuration>
   2:   <system.serviceModel>
   3:     <standardEndpoints>
   4:       <webHttpEndpoint>
   5:         <standardEndpoint crossDomainScriptAccessEnabled="true"/>
   6:       </webHttpEndpoint>
   7:     </standardEndpoints>
   8:     <bindings>
   9:       <webHttpBinding>
  10:         <binding crossDomainScriptAccessEnabled="true" />
  11:       </webHttpBinding>
  12:     </bindings>
  13:     <services>      
  14:       <service name="Artech.WcfServices.Service.EmployeesService">
  15:         <endpoint kind="webHttpEndpoint" 
  16:                   address="http://127.0.0.1:3721/employees"
  17:                   contract="Artech.WcfServices.Service.Interface.IEmployees"/>
  18:       </service>
  19:     </services>
  20:   </system.serviceModel>
  21: </configuration>

在客户端,我们在一个Web页面中通过jQuery进行Ajax调用这个服务,并将得到的员工列表显示在一个表格中。出CSS之外的页面代码如下所示,需要注意的是在进行Ajax调用的使用将dataType选项设置成“jsonp”,而不是“json”。

   1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2: <html xmlns="http://www.w3.org/1999/xhtml">
   3:   <head>
   4:     <title>员工列表</title>
   5:     <style type="text/css">
   6:        ...
   7:     </style>
   8:     <script src="Scripts/jquery-1.7.1.js" type="text/javascript"></script>
   9:     <script type="text/javascript">
  10:         $(function () {
  11:             $.ajax({
  12:                 type: "get",
  13:                 url: "http://127.0.0.1:3721/employees/all",
  14:                 dataType: "jsonp",
  15:                 success: function (employees) {
  16:                     $.each(employees, function (index, value) {
  17:                         var detailUrl = "detail.html?id=" + value.Id;
  18:                         var html = "<tr><td>";
  19:                         html += value.Id + "</td><td>";
  20:                         html += "<a href='" + detailUrl + "'>" + value.Name + "</a></td><td>";
  21:                         html += value.Grade + "</td><td>";
  22:                         html += value.Department + "</td></tr>";
  23:                         $("#employees").append(html);
  24:                     });
  25:                     $("#employees tr:odd").addClass("oddRow");
  26:                 }
  27:             });
  28:         });
  29:      </script>
  30:   </head>
  31:   <body>
  32:     <table id="employees" width="600px">
  33:         <tr>
  34:             <th>ID</th>
  35:             <th>姓名</th>
  36:             <th>级别</th>
  37:             <th>部门</th>
  38:         </tr>
  39:     </table>
  40: </body>
  41: </html>

当服务启动后在浏览器中显示上面这个Web页面,会得到如下所示的员工列表。

image

posted @ 2012-01-16 21:17 Artech 阅读(2467) 评论(17) 编辑 收藏

 回复 引用 查看   
#1楼 2012-01-16 21:32 彦斌      
关注,期待新书早点面市
 回复 引用 查看   
#2楼 2012-01-16 22:07 明海哥哥      
LZ好,有两点想请教下,希望能得到您的解答,不胜感激:
1.如何解决jsonp支持同步,我知道的好像只支持异步
2.如何解决jsonp支持post,我知道的好像只支持get

谢谢!!!!祝新年快乐

 回复 引用 查看   
#3楼[楼主] 2012-01-16 22:18 Artech      
引用明海哥哥:
LZ好,有两点想请教下,希望能得到您的解答,不胜感激:
1.如何解决jsonp支持同步,我知道的好像只支持异步
2.如何解决jsonp支持post,我知道的好像只支持get

谢谢!!!!祝新年快乐

坦率地说,你"知道的"也是我"知道的",看问看别人能否解答这两个问题。

 回复 引用 查看   
#4楼[楼主] 2012-01-16 22:19 Artech      
引用彦斌:关注,期待新书早点面市

谢谢,祝新年快乐。

 回复 引用 查看   
#5楼 2012-01-16 22:38 魔君六道      
老A怎么从后台跳到前台拉?
 回复 引用 查看   
#6楼[楼主] 2012-01-16 22:55 Artech      
引用魔君六道:老A怎么从后台跳到前台拉?

什么都略懂一点,生活更精彩一点,哈!

 回复 引用 查看   
#7楼 2012-01-16 22:59 紫青城      
get方式请求,更本涉及不到跨域吧。任何url资源都可以通过get请求的。get请求有一点定局限性,只支持少量数据传入。如何能post跨域呢?
 回复 引用 查看   
#8楼 2012-01-17 01:48 水牛刀刀      
引用紫青城:get方式请求,更本涉及不到跨域吧。任何url资源都可以通过get请求的。get请求有一点定局限性,只支持少量数据传入。如何能post跨域呢?
get请求也有跨域问题的。普通的ajax发起的get请求得不到数据的。

 回复 引用   
#9楼 2012-01-17 09:20 kevinlzf[未注册用户]
ding
 回复 引用   
#10楼 2012-01-17 09:28 NanChen[未注册用户]
继续往这个方向走,最好移动起来。
 回复 引用 查看   
#11楼 2012-01-17 09:38 Tony Zhou      
wcf这方面做的还真不错
 回复 引用   
#12楼 2012-01-17 09:45 匿名2[未注册用户]
请问有什么方式支持POST跨域吗?
 回复 引用 查看   
#13楼 2012-01-17 10:19 magic_evan      
引用Artech:
引用明海哥哥:
LZ好,有两点想请教下,希望能得到您的解答,不胜感激:
1.如何解决jsonp支持同步,我知道的好像只支持异步
2.如何解决jsonp支持post,我知道的好像只支持get

谢谢!!!!祝新年快乐

坦率地说,你"知道的"也是我"知道的",看问看别人能否解答这两个问题。

给JSONP执行的函数传递一个Handler的参数,执行完成后就调用这个Handler有点像JAVA里的事件通知方式
function MyHandler()
{
alert('todo');
}

function MyJonp(ptr)
{
$.ajax(function(){
//todo……
ptr();
})
}

MyJonp(MyHandler);使用这样是不是第一个问题要的效果呢?

 回复 引用 查看   
#14楼 2012-01-18 09:37 GaryChen      
好久没来看老A的文章了,支持一个......收藏了
 回复 引用 查看   
#15楼[楼主] 2012-01-18 09:45 Artech      
引用GaryChen:好久没来看老A的文章了,支持一个......收藏了

还好是不没有看,不是我没有写:)
新年快乐!

 回复 引用 查看   
#16楼 2012-01-18 11:00 GaryChen      
@Artech
新年快乐,期待你的新文章.....

 回复 引用 查看   
#17楼 2012-01-19 17:21 流氓の影      
同求POST跨域

目前解决办法是写个同域服务桥接。。。。。。

不然get请求的时候参数传个JSON字符串很蛋疼。。。不但要替换掉例如/:\等特殊字符。。。还要考虑长度问题 - - 因为传递中文信息OR标点符号时候存在URLENCODE的问题,有时候一个对象都传不回去。。。。。

现在被虐的已经很老实的按照REST服务书写规范进行传值了,不敢偷懒传Json字符串。每个对象请求一次服务。。。。

A大 求解脱

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 2324092 E6huU/zT+Gg=