将 JSON 数据从 JQuery 发送到 WCF REST 方法时出现问题
我在让 jquery 将一些 json 数据发布到 WCF 服务上的休息方法时遇到一些问题。
在 WCF 方面,这是操作契约:
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "PostSomething")]
MyResult PostSomething(MyRequest request);
MyResult
和 MyRequest
都标记有所有必要的 DataContract
和 DataMember
> 属性和服务正在公开 WebHttp 端点。
在 JQuery 方面,这是我的函数调用:
var jsonStr = JSON.stringify(reqObj);
$.ajax({
type: "POST",
dataType: "json",
url: "http://localhost/MyService/PostSomething",
contentType: "application/json; charset=utf-8",
data: jsonStr,
success: function (html) {
alert(html);
}
});
此请求永远不会到达我的方法(我每次都会收到 405 不允许的方法),并且在 Charles 中查看该请求如下所示:
OPTIONS /MyService/PostSomething HTTP/1.1
Host: localhost
Cache-Control: max-age=0
Access-Control-Request-Method: POST
Origin: null
Access-Control-Request-Headers: Content-Type, Accept
Accept: */*
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.237 Safari/534.10
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
有几件事对此很奇怪:
- 该方法是 OPTIONS不发布
- 内容类型(在另一个选项卡中)显示
text/html; charset=UTF-8
而不是 json, - JSON 数据在任何地方都看不到
但是,如果我修改 Charles 中的请求,使其标头类似于解决方案 此处,然后一切正常:
POST /MyService/PostSomething HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost
Content-Length: 152
{"Id":"", "Name":"testspot","Description":"test" }
查看教程和其他问题这里其他人已经设法让 JQuery 发布到像这样的 WCF REST 方法,而我对我在这里做错了什么感到不知所措..
哦,为了说明一些背景,这是一个 WCF 4 服务,我我正在使用 JQuery 1.4.4。
谢谢,
更新:
经过更多阅读并感谢 Darrel 向我指出跨域规范,我通过在服务接口上对我的服务进行了一些小的更改,成功地取得了进一步的进展:
[OperationContract]
[WebInvoke(Method = "*",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "PostSomething")]
MyResult PostSomething(MyRequest request);
在实现中,我需要检查传入的请求是否是针对 OPTIONS 的,在这种情况下返回一些标头而不是执行预期的工作:
if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");
return null;
}
然后该方法被调用两次,第一次服务器返回 null 但将一些标头添加到客户端,然后使用 POST 作为方法发出实际请求,服务器继续正常处理该请求。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(5)
包含建议解决方案的问题的更新存在一些问题 - 问题是,如果您的输入不支持 POST 方法,则 OPTIONS 请求实际上不会返回正确的允许标头。它实际上并没有考虑 WCF 端点上实际允许哪些方法 - 它只是人为地表示当客户端执行 OPTIONS 请求时应用程序中的每个端点都允许“POST”(这实际上是客户端询问支持什么) )。
如果您并不真正依赖 OPTIONS 方法中的信息来返回有效的方法列表(就像某些 CORS 请求的情况),这可能没问题 - 但如果您是这样,您将需要执行类似的操作这个问题的解答:
如何使用 WCF self 处理 Ajax JQUERY POST 请求-host
基本上,每个端点应该实现:
Webinvoke(Method="OPTIONS", UriTemplate="")
并调用适当的方法,将正确的标头加载到响应中(包括正确的标头)该端点的“Access-Control-Allow-Method”列表)发送给调用者。托管的 WCF 端点不会自动为我们执行此操作,这有点糟糕,但这是一种允许对端点进行更精细控制的解决方法。
在该解决方案中,正确的响应标头会在端点实现中加载:
public void GetOptions()
{
// The data loaded in these headers should match whatever it is you support on the endpoint
// for your application.
// For Origin: The "*" should really be a list of valid cross site domains for better security
// For Methods: The list should be the list of support methods for the endpoint
// For Allowed Headers: The list should be the supported header for your application
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
}
除此之外,您还应该在绑定端点的 web.config 中设置“CrossDomainScriptAccessEnabled”标志,或者在配置端点时在 WebHttpBinding 的代码中设置“CrossDomainScriptAccessEnabled”标志。否则,当您说“Access-Control-Allow-Origin”是“*”(或 URL 列表)时,您再次在标头响应中撒谎
更新:
尝试将 .svc 放在 MyService 之后,以便 URL 显示
http://localhost/MyService.svc/PostSomething
我前几天自己正在研究这个问题,并在 Rick Strahl 的博客上看到了一篇文章:
http://www.west-wind.com/weblog/posts/324917.aspx
这对我来说完美无缺,所以试试吧!
希望有帮助! :)
我只会发布一个对我有帮助的简短答案,因为其他答案没有。
- 场景:ajax调用wcf服务。
- 错误原因:发送 POST 之前来自 ajax 的自动 OPTIONS 请求
要求。我的服务无法处理第一个请求。 - 解决方案:允许OPTIONS请求,并响应它。
您需要做什么:
将其添加到 web.config:
; <自定义标题> <添加名称=“Access-Control-Allow-Origin”值=“*”/> <添加名称=“Access-Control-Allow-Methods”值=“GET、PUT、POST、DELETE、OPTIONS”/> <添加名称=“Access-Control-Allow-Headers”值=“内容类型”/> 将此文件添加到 Global.asax.cs(如果您的解决方案中没有此文件,请通过以下方式创建它:添加新项目 => Visual C# => 全局应用程序类(默认名称为“Global.asax.cs”) asax”)):
protected void Application_BeginRequest(对象发送者,EventArgs e) { if (HttpContext.Current.Request.HttpMethod == "选项") HttpContext.Current.Response.End(); }
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
这似乎是 Firefox 的一个功能,可以避免跨域调用。请参阅 http://www.petefreitag.com/item/703.cfm
的规范这是这里 http://www.w3.org/TR/cors/ 并在非常简短地阅读,看来因为您正在进行跨域调用,所以您的服务应该实现 OPTIONS 方法并返回一些允许发送 POST 方法的标头。
This seems to be a Firefox thing for avoiding cross domain calls. See http://www.petefreitag.com/item/703.cfm
The spec for this is here http://www.w3.org/TR/cors/ and after a very brief read, it appears that because you are doing a cross domain call, your service is expected to implement the OPTIONS method and return some headers that allow the POST method to be sent.