关于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)]
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 >
< serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
< bindings >
< webHttpBinding >
< binding crossDomainScriptAccessEnabled="true">
</ binding >
</ webHttpBinding >
</ bindings >
< behaviors >
< serviceBehaviors >
< behavior >
< serviceMetadata httpGetEnabled="true"/>
< 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;
}
$( "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 ,如需转载请自行联系原作者