使用 WCF Rest 的错误跨域调用
Error cross domain call using WCF Rest
我正在尝试使用 CORS 调用创建 WCF 服务,到目前为止,我的服务器具有此处指示的 类:http://enable-cors.org/server_wcf.html
我能够使用不带任何参数的动词 GET 通过 jQuery ajax 调用进行调用,当我尝试将参数传递给我的请求时出现问题,这是我的代码:
界面标记:
[OperationContract]
[WebInvoke(Method = "*",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetData(TestClass value);
方法标记:
public string GetData(TestClass value)
{
return value.Id.ToString();
}
js 标记:
var value = {
Id : "2",
Name: "qwe"
};
$.ajax({
url: "http://localhost:38733/Service1.svc/GetData",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ value: value }),
success: function(result) {
console.log(result);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
但是如果我调试,我总是得到 null,这意味着参数没有传递给方法,我还在 Chrome 控制台上得到 POST http://localhost:38733/Service1.svc/GetData 400 (Bad Request)
。
我做错了什么?
UPDATE
Web.config 标记:
<behavior name="jsonBehavior">
<webHttp />
<crossOriginResourceSharingBehavior />
</behavior>
<extensions>
<behaviorExtensions>
<add name="crossOriginResourceSharingBehavior"
type="WCFSecureService.EnableCrossOriginResourceSharingBehavior, WCFSecureService, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
<services>
<service name="WCFSecureService.Service1">
<endpoint address=""
binding="webHttpBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
在 Google Chrome 控制台上,我得到以下信息:
OPTIONS http://localhost:38733/Service1.svc/GetData?value=5
UPDATE
如果我向一个没有任何参数的方法发出请求,它会起作用
UPDATE
Fiddler 2 向我展示了这个,所以我不知道我做错了什么...
UPDATE
测试类标记:
[DataContract]
public class TestClass
{
private int id;
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
[DataMember]
public int Id
{
get { return id; }
set { id = value; }
}
}
UPDATE
如果我使用 JSON.stringify({ value: value })
和 BodyStyle = WebMessageBodyStyle.Bare
我到达了服务器,但是我得到的所有属性都是 0,检查下一张图片:
在您的服务合同中,您可能希望放置一个可选的 WebGet
指令。
[WebGet(UriTemplate = "GetData/{value}")]
string GetData(int value);
要查找的另一件事是您在 web.config 中为您的 enpoint 定义了 json
行为。
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
<behavior name="xmlBehavior">
<webHttp defaultOutgoingResponseFormat="Xml"/>
</behavior>
</endpointBehaviors>
注意:如果您使用的是行为,则需要按以下方式指定格式
http://localhost:38733/Service1.svc/json/GetData/5
或
http://localhost:38733/Service1.svc/xml/GetData/5
另外,你能试试这个 js:
var _data= {
value:5
};
$.ajax({
...
data: _data,
success: function(data) {
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
或反过来:
$.ajax({
url: "http://localhost:38733/Service1.svc/json/GetData/5",
});
我找到了适合我的情况的解决方案。最后这是一个测试,所以我将使用更多的参数,而不仅仅是一个参数,这就是我学到的:
- 对于多个参数,请求必须被包装,所以,
WebInvoke
的合同注释必须是 BodyStyle =
WebMessageBodyStyle.WrappedRequest
.
在客户端,只有一个参数,使用JSON.stringify(value)
是可以的,但是如果超过一个,你就得更具体,例如:
data: JSON.stringify({
value: value,
text: "any text"
});
关于 link 我提供的问题,我必须包括两个类
CustomHeaderMessageInspector
和
EnableCrossOriginResourceSharingBehavior
, 看来他们是
如果您可以使用 global.asax 文件,则不再需要,您
只需将以下代码添加到 Application_BeginRequest:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET");
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.config
是这样结束的:
<bindings>
<webHttpBinding>
<binding name="Binding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="corsBinding" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<services>
<service name="WCFSecureService.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="bs" binding="basicHttpBinding" contract="WCFSecureService.IService1" />
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration="corsBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="jsonBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
感谢您的帮助,我希望它能帮助其他人。
我正在尝试使用 CORS 调用创建 WCF 服务,到目前为止,我的服务器具有此处指示的 类:http://enable-cors.org/server_wcf.html
我能够使用不带任何参数的动词 GET 通过 jQuery ajax 调用进行调用,当我尝试将参数传递给我的请求时出现问题,这是我的代码:
界面标记:
[OperationContract]
[WebInvoke(Method = "*",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetData(TestClass value);
方法标记:
public string GetData(TestClass value)
{
return value.Id.ToString();
}
js 标记:
var value = {
Id : "2",
Name: "qwe"
};
$.ajax({
url: "http://localhost:38733/Service1.svc/GetData",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ value: value }),
success: function(result) {
console.log(result);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
但是如果我调试,我总是得到 null,这意味着参数没有传递给方法,我还在 Chrome 控制台上得到 POST http://localhost:38733/Service1.svc/GetData 400 (Bad Request)
。
我做错了什么?
UPDATE
Web.config 标记:
<behavior name="jsonBehavior">
<webHttp />
<crossOriginResourceSharingBehavior />
</behavior>
<extensions>
<behaviorExtensions>
<add name="crossOriginResourceSharingBehavior"
type="WCFSecureService.EnableCrossOriginResourceSharingBehavior, WCFSecureService, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
<services>
<service name="WCFSecureService.Service1">
<endpoint address=""
binding="webHttpBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
在 Google Chrome 控制台上,我得到以下信息:
OPTIONS http://localhost:38733/Service1.svc/GetData?value=5
UPDATE
如果我向一个没有任何参数的方法发出请求,它会起作用
UPDATE
Fiddler 2 向我展示了这个,所以我不知道我做错了什么...
UPDATE
测试类标记:
[DataContract]
public class TestClass
{
private int id;
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
[DataMember]
public int Id
{
get { return id; }
set { id = value; }
}
}
UPDATE
如果我使用 JSON.stringify({ value: value })
和 BodyStyle = WebMessageBodyStyle.Bare
我到达了服务器,但是我得到的所有属性都是 0,检查下一张图片:
在您的服务合同中,您可能希望放置一个可选的 WebGet
指令。
[WebGet(UriTemplate = "GetData/{value}")]
string GetData(int value);
要查找的另一件事是您在 web.config 中为您的 enpoint 定义了 json
行为。
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
<behavior name="xmlBehavior">
<webHttp defaultOutgoingResponseFormat="Xml"/>
</behavior>
</endpointBehaviors>
注意:如果您使用的是行为,则需要按以下方式指定格式
http://localhost:38733/Service1.svc/json/GetData/5
或
http://localhost:38733/Service1.svc/xml/GetData/5
另外,你能试试这个 js:
var _data= {
value:5
};
$.ajax({
...
data: _data,
success: function(data) {
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
或反过来:
$.ajax({
url: "http://localhost:38733/Service1.svc/json/GetData/5",
});
我找到了适合我的情况的解决方案。最后这是一个测试,所以我将使用更多的参数,而不仅仅是一个参数,这就是我学到的:
- 对于多个参数,请求必须被包装,所以,
WebInvoke
的合同注释必须是BodyStyle = WebMessageBodyStyle.WrappedRequest
. 在客户端,只有一个参数,使用
JSON.stringify(value)
是可以的,但是如果超过一个,你就得更具体,例如:data: JSON.stringify({ value: value, text: "any text" });
关于 link 我提供的问题,我必须包括两个类
CustomHeaderMessageInspector
和EnableCrossOriginResourceSharingBehavior
, 看来他们是 如果您可以使用 global.asax 文件,则不再需要,您 只需将以下代码添加到 Application_BeginRequest:HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET"); 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.config
是这样结束的:
<bindings>
<webHttpBinding>
<binding name="Binding" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="corsBinding" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<services>
<service name="WCFSecureService.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="bs" binding="basicHttpBinding" contract="WCFSecureService.IService1" />
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration="corsBinding"
behaviorConfiguration="jsonBehavior"
contract="WCFSecureService.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="jsonBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
感谢您的帮助,我希望它能帮助其他人。