实现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  ,如需转载请自行联系原作者

相关文章
|
3月前
|
Devops 持续交付 测试技术
JSF遇上DevOps:开发流程将迎巨变?一篇文章带你领略高效协同的魅力!
【8月更文挑战第31天】本文探讨了如何在JavaServer Faces(JSF)开发中融入DevOps文化,通过持续集成与部署、自动化测试、监控与日志记录及反馈机制,提升软件交付速度与质量。文中详细介绍了使用Jenkins进行自动化部署、JUnit与Selenium进行自动化测试、ELK Stack进行日志监控的具体方法,并强调了持续改进的重要性。
36 0
|
3月前
|
XML JSON 前端开发
AJAX是什么?原生语法格式?jQuery提供分装好的AJAX有什么区别?
AJAX是什么?原生语法格式?jQuery提供分装好的AJAX有什么区别?
31 0
|
5月前
|
JavaScript 前端开发 安全
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
|
4月前
|
前端开发 JavaScript API
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
48 0
|
5月前
|
前端开发 JavaScript 安全
详尽分享突破ajax不能跨域的限制
详尽分享突破ajax不能跨域的限制
32 0
|
6月前
|
JavaScript 索引
jQuery 实现 图片框切换【与原生 JS 对比】
jQuery 实现 图片框切换【与原生 JS 对比】
|
6月前
|
JSON 前端开发 JavaScript
JavaScript原生实现AJAX技术详解
【4月更文挑战第22天】本文详细介绍了使用原生JavaScript实现AJAX技术,包括基本原理和步骤。AJAX借助`XMLHttpRequest`对象实现异步通信,允许网页在不刷新情况下与服务器交换数据。文中提供示例展示了如何创建请求、设置回调函数、处理响应数据以及设置请求头和发送不同类型的数据。此外,还讨论了跨域问题及其解决方案,如CORS和JSONP。掌握这些基础知识对前端开发者至关重要,尽管现代框架提供了更高级的抽象。
|
6月前
|
移动开发 前端开发 安全
Ajax跨域的所有方法(最详细带使用教程!!!)
Ajax跨域的所有方法(最详细带使用教程!!!)
|
6月前
|
XML 前端开发 JavaScript
AJAX - 创建 XMLHttpRequest 对象
AJAX - 创建 XMLHttpRequest 对象
|
6月前
|
XML 前端开发 JavaScript
AJAX - 创建 XMLHttpRequest 对象
AJAX - 创建 XMLHttpRequest 对象