实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法

简介:

关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace  WcfService1
{
     [ServiceContract]
     public  interface  IAddService
     {
 
         [OperationContract]
         [WebInvoke(Method= "GET" ,RequestFormat=WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,BodyStyle=WebMessageBodyStyle.WrappedRequest)]
         int  Add2( int  a, int  b);
     }
}
 
 
namespace  WcfService1
{
     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
     //[JavascriptCallbackBehavior(UrlParameterName="jsoncallback")] //不指定的时采用默认的callback回调参数
     public  class  AddService : IAddService
     {
         public  int  Add2( int  a,  int  b)
         {
             return  a + b;
         }
 
     }
}

创建一个WCF服务文件,文件内容:

1
<%@ ServiceHost Language="C#" Debug="true" Service="WcfService1.AddService" %>

上面实现的是支持GET方法请求调用,下面就是配置WEB.CONFIG,使其支持跨域调用,注意我将standardEndpoints注释掉了,当然如果不注释也不会有什么影响,关键是bindings节点中的属性:crossDomainScriptAccessEnabled="true",如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
< system.serviceModel >
   <!--<standardEndpoints>
     <webHttpEndpoint>
       <standardEndpoint crossDomainScriptAccessEnabled="true" />
     </webHttpEndpoint>
   </standardEndpoints>-->
   < serviceHostingEnvironment  multipleSiteBindingsEnabled="true" />
   < bindings >
     < webHttpBinding >
       < binding  crossDomainScriptAccessEnabled="true">
       </ binding >
     </ webHttpBinding >
   </ bindings >
   < behaviors >
     < serviceBehaviors >
       < behavior >
         <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
         < serviceMetadata  httpGetEnabled="true"/>
         <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
         < serviceDebug  includeExceptionDetailInFaults="true"/>
       </ behavior >
     </ serviceBehaviors >
     < endpointBehaviors >
       < behavior  name="AddServiceBehavior">
         < enableWebScript  />
       </ behavior >
     </ endpointBehaviors >
   </ behaviors >
   < services >
     < service  name="WcfService1.AddService">
       < endpoint  address=""  binding="webHttpBinding" contract="WcfService1.IAddService" behaviorConfiguration="AddServiceBehavior" ></ endpoint >
     </ service >
   </ services >
</ system.serviceModel >

创建Global.asax文件并添加如下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected  void  Application_BeginRequest( object  sender, EventArgs e)
{
     HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
     HttpContext.Current.Response.Cache.SetNoStore();
 
     EnableCrossDmainAjaxCall();
}
 
private  void  EnableCrossDmainAjaxCall()
{
     HttpContext.Current.Response.AddHeader( "Access-Control-Allow-Origin" , "*" );
 
     if  (HttpContext.Current.Request.HttpMethod ==  "OPTIONS" )
     {
         HttpContext.Current.Response.AddHeader( "Access-Control-Allow-Methods" ,
                       "GET, POST" );
         HttpContext.Current.Response.AddHeader( "Access-Control-Allow-Headers" ,
                       "Content-Type, Accept" );
         HttpContext.Current.Response.AddHeader( "Access-Control-Max-Age" ,
                       "1728000" );
         HttpContext.Current.Response.End();
     }
}

下面是实现WEB端跨域调用WCF服务代码

1.采用原生的XMLHttpRequest跨域调用WCF服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//简单封装
         var  $ =  function  (id) {
             return  document.getElementById(id);
         };
 
         function  getXMLHTTPRequest() {
             var  req =  false ;
             try  {
                 req =  new  XMLHttpRequest();
             catch  (err) {
                 try  {
                     req =  new  ActiveXObject( "Msxml2.XMLHTTP" );
                 catch  (err) {
                     try  {
                         req =  new  ActiveXObject( "Microsoft.XMLHTTP" );
                     catch  (err) {
                         req =  false ;
                     }
                 }
             }
             return  req;
         }
 
//以下为按钮的点击事件,我采用的同步调用,当然也可以采用回调方式,回调方式的话就需要在请求的URL中加入:callback=回调方法,然后再定义一个回调方法即可
         $( "btnGet" ).onclick =  function  () {
             var  querystr =  "a="  + $( "num1" ).value +  "&b="  + $( "num2" ).value;
             var  xmlhttp = getXMLHTTPRequest();
             xmlhttp.open( "GET" "http://localhost:30348/addservice.svc/Add2?"  + querystr,  false );
             xmlhttp.send();
             var  r = eval( "("  + xmlhttp.responseText +  ")" );
             $( "result" ).value = r.d;
         }

 

 

2.通过动态以JS方式请求WCF地址资源实现原始的跨域方法,虽然可以实现跨域调用,但只支持GET方式,如果需要支持POST这个方案就无解:

1
2
3
4
5
6
7
8
9
10
11
12
13
$( "btnGet" ).onclick =  function  () {
     var  querystr =  "a="  + $( "num1" ).value +  "&b="  + $( "num2" ).value;
     var  script =document.getElementById( "crossDomainScript_wcf" ) || document.createElement( "script" );
     script.type =  "text/javascript" ;
     script.id =  "crossDomainScript_wcf" ;
     script.src =  "http://localhost:30348/addservice.svc/Add2?callback=success_callback&"  + querystr;
     document.getElementsByTagName( "head" )[0].appendChild(script);
}
 
//回调方法
function  success_callback(data) {
     $( "result" ).value = data;
}

以下是POST调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$( "btnGet" ).onclick =  function  () {
     var  xmlhttp = getXMLHTTPRequest();
     xmlhttp.open( "POST" "http://localhost:30348/addservice.svc/Add2" true );
     xmlhttp.setRequestHeader( "Content-Type" "application/json" );
     xmlhttp.onreadystatechange =  function  () {
         alert(xmlhttp.status);
         if  (xmlhttp.readyState == 4) {
             if  (xmlhttp.status == 200) {
                 var  r = eval( "("  + xmlhttp.responseText +  ")" );
                 $( "result" ).value = r.d;
             }
         }
     };
     xmlhttp.send( '{"a":'  + $( "num1" ).value +  ',"b":'  + $( "num2" ).value +  '}' );
}

2.采用jQuery.ajax来调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var  jq = jQuery.noConflict();
jq( "#btnGet" ).click( function  () {
     jq.ajax( "http://localhost:30348/AddService.svc/Add2" , {
         type:  "get" ,
         dataType:  "jsonp" ,
         data:  'a='  + jq( "#num1" ).val() +  '&b='  + jq( "#num2" ).val(),
         success:  function  (data) {
             jq( "#result" ).val(data);
         },
         error:  function  (x, textStatus, errorThrown) {
             alert( "error:"  + textStatus);
         }
     });
});

其实可按正常方式直接调用,无需采用JSONP,因为WCF服务端已支持跨域调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var  jq = jQuery.noConflict();
jq( "#btnGet11" ).click( function  () {
     jq.ajax( "http://localhost:30348/AddService.svc/Add2" , {
         type:  "GET" ,
         dataType:  "json" ,
         data:  'a='  + jq( "#num1" ).val() +  '&b='  + jq( "#num2" ).val(),
         success:  function  (data) {
             jq( "#result" ).val(data.d);
         },
         error:  function  (x, textStatus, errorThrown) {
             alert( "error:"  + textStatus);
         }
     });
});

  

当然传参时也可以用JSON的写法(注意POST与GET的JSON写法有所不同,POST时键值必需是严格的JSON字符串,GET时是一个JS对象),再此就不作说明

POST调用:(注意上述JQUERY.AJAX 采用JSONP+GET模式不适用于POST模式,因为经调试,发现采用JSONP模式,终始发起的是GET请求,采用的原理是上面我写的原始跨域调用方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var  jq = jQuery.noConflict();
jq( "#btnGet" ).click( function  () {
     jq.ajax( "http://localhost:30348/AddService.svc/Add2" , {
         type:  "POST" ,
         dataType:  "json" ,
         contentType:  "application/json" ,
         data:  '{"a":'  + jq( "#num1" ).val() +  ',"b":'  + jq( "#num2" ).val() +  '}' ,
         success:  function  (data) {
             jq( "#result" ).val(data.d);
         },
         error:  function  (x, textStatus, errorThrown) {
             alert( "error:"  + textStatus);
         }
     });
});

这里针对跨域再特别说明一下,若采用AJAX跨域调用时,会发送两次请求,第一次为OPTIONS,用于服务器进行预检,第二次才会发出真正的请求,这也就是为什么WCF服务的Global.asax需要添加EnableCrossDmainAjaxCall的原因。本人在研究跨域调用WCF时,走了很多弯路,也尝试过很多方法,但最终还是弄明白了,希望大家能从这篇博文中受益,文中不足之处,敬请指出,谢谢!

本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4820117.html  ,如需转载请自行联系原作者

相关文章
|
29天前
|
JavaScript 前端开发 容器
AJAX载入外部JS文件到页面并让其执行的方法(附源码)
AJAX载入外部JS文件到页面并让其执行的方法(附源码)
28 0
|
29天前
|
前端开发
AJAX发送请求方法封装和请求函数底层刨析以及axios二次封装
AJAX发送请求方法封装和请求函数底层刨析以及axios二次封装
|
29天前
|
移动开发 前端开发 安全
Ajax跨域的所有方法(最详细带使用教程!!!)
Ajax跨域的所有方法(最详细带使用教程!!!)
|
29天前
|
数据采集 Web App开发 前端开发
Python爬虫之Ajax分析方法与结果提取#6
Ajax分析方法、Ajax结果提取【2月更文挑战第20天】
51 0
Python爬虫之Ajax分析方法与结果提取#6
|
29天前
|
XML 前端开发 JavaScript
AJAX get() 和 post() 方法
AJAX(Asynchronous JavaScript and XML)是一种用于创建快速和动态网页的技术,它允许使用 JavaScript 和 XMLHttpRequest 对象在不重新加载整个页面的情况下向服务器发送请求和接收响应。jQuery 提供了几个用于 AJAX 操作的方法,包括 .ajax()、.get() 和 .post()
23 1
|
JSON JavaScript 前端开发
jquery调WCF
在项目中用过一些WCF的技术这篇文章是对以前用过的一点东西的一个梳理   一,webconfig的配置除了一般的配置外,与WCF相关的配置如下                                                                           ...
806 0
|
8月前
|
JavaScript
Jquery插件知识之Jquery.cookie实现页面传值
Jquery插件知识之Jquery.cookie实现页面传值
39 0
|
9月前
|
JavaScript
jQuery 插件自用列表
jQuery 插件自用列表
32 0
|
29天前
|
JavaScript
jQuery图片延迟加载插件jQuery.lazyload
jQuery图片延迟加载插件jQuery.lazyload
|
10月前
|
JavaScript
jQuery编写插件的两种方法
jQuery编写插件的两种方法
59 0