将JSON数据从JQuery发送到WCF REST方法时出现问题

我在使用jquery将一些json数据发布到我在WCF服务上的rest方法时遇到了一些麻烦。

在WCF方面,这是操作合同:

[OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "PostSomething")] MyResult PostSomething(MyRequest request); 

MyResultMyRequest都标有所有必需的DataContractDataMember属性,服务正在暴露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 

对此有些奇怪的事情:

  1. 方法是OPTIONS而不是POST
  2. 内容类型(在另一个标签中)显示text/html; charset=UTF-8 text/html; charset=UTF-8而不是json
  3. 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作为方法,服务器继续正常处理请求。

这似乎是一个避免跨域调用的Firefox。 见http://www.petefreitag.com/item/703.cfm

这里的规范是http://www.w3.org/TR/cors/ ,经过非常简短的阅读,似乎因为你正在进行跨域调用,你的服务应该实现OPTIONS方法并返回一些允许发送POST方法的标头。

包含建议解决方案的问题的更新存在一些问题 – 问题在于,如果您的输入不支持POST方法,则OPTIONS请求实际上不会返回正确的允许标头。 它实际上并没有考虑WCF端点上实际允许哪些方法 – 当客户端执行OPTIONS请求时,它只是人为地说应用程序中的每个端点都允许“POST”(实际上客户端询问支持什么) )。

这可能没问题,如果你真的不依赖于OPTIONS方法中的信息来返回一个有效的方法列表(就像一些CORS请求那样) – 但是如果你这样做,你需要做类似的事情。关于这个问题的解决方案: 如何使用WCF自托管处理Ajax JQUERY POST请求

基本上,每个端点应该实现:

Webinvoke(Method="OPTIONS", UriTemplate="")

并调用一个适当的方法,将适当的头加载到响应者(包括该端点的正确“访问控制允许 – 方法”列表)给调用者。 托管的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的代码。 否则,当您说“Access-Control-Allow-Origin”为“*”(或URL列表)时,您将再次处于标题响应中

更新:

尝试在MyService之后放置.svc以便URL读取

 http://localhost/MyService.svc/PostSomething 

我前几天正在研究这个问题,并在Rick Strahl的博客上发表了一篇文章:

http://www.west-wind.com/weblog/posts/324917.aspx

这对我来说完美无缺,所以试一试!

希望有所帮助! 🙂

在你的web.config中你使用过webhttpbinding吗?

只有webhttpbinding支持json。

我会发一个帮助我的简短回答,因为其他答案没有。

  • 场景:ajax调用wcf服务。
  • 错误原因:在发送POST请求之前从ajax发出自动OPTIONS请求。 我的服务无法处理第一个请求。
  • 解决方案:允许OPTIONS请求,并对其进行响应。

你需要做什么:

  1. 将其添加到web.config:

             

  2. 将其添加到Global.asax.cs(如果您的解决方案中没有此文件,则通过以下方式创建:Add new item => Visual C#=> Global Application Class(默认名称为“Global.asax”)):

     protected void Application_BeginRequest(object sender, EventArgs e) { if (HttpContext.Current.Request.HttpMethod == "OPTIONS") HttpContext.Current.Response.End(); }