预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400
Posted
技术标签:
【中文标题】预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400【英文标题】:Wcf webHttpBinding Response for preflight has invalid HTTP status code 400 【发布时间】:2016-05-19 17:29:56 【问题描述】:我按照 Ido Flatow 的 post 创建了一个跨域请求并创建了以下内容:
在我的服务接口上:
[OperationContract]
[WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
bool GetUserAuthentication(string userLoginName, string password);
在 app.config 上:
<behaviors>
<endpointBehaviors>
<behavior name="webSupport">
<webHttp />
<CorsSupport />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="CorsSupport" type="WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
现在我正在使用 angular $http 服务发送一个简单的发布请求,它在 IE 和 Edge(也在 Postman)上运行,但无法在 Chrome 和 Firefox 上运行,并出现以下错误:
XMLHttpRequest 无法加载 http://localhost:5280/MetaDataService/GetUserAuthentication。回复 对于预检有无效的 HTTP 状态代码 400
Chrome 错误打印屏幕:
【问题讨论】:
【参考方案1】:Chrome 正在预检请求以查找 CORS 标头。如果请求是可接受的,它将发送真正的请求。
我的问题是发送到我的 WCF 服务器的 OPTIONS 请求被拒绝了我为我的方法定义了Method="*"
,导致选项请求被定向到我的方法并期望获得参数。
基于How to handle Ajax JQUERY POST request with WCF self-host 问题的解决方案是添加新的 OperationContract 来处理 OPTIONS 请求:
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void GetOptions();
public void GetOptions()
此方法获取所有选项请求并允许将真正的 POST 方法定向到我的服务方法。
【讨论】:
那么你应该在 GetOptions 方法中做什么?好像是空的?【参考方案2】:1.将此 API 添加到 IRestService(您的服务接口)
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void Options();
2.在RestService中实现这个功能(你的服务实现)
public void Options()
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");
CORS 操作
CORS 世界中有两种类型的请求,“正常”请求和预检请求。正常请求是页面通常会向服务发出的请求,带有一个额外的标头“Origin”,它指示来源,服务可以确定是否允许来自该来源的跨域调用(通过“访问-Control-Allow-Origin”响应标头)。 “安全”请求(GET 和 HEAD)仅使用额外的标头来工作。浏览器会将 Origin 标头添加到去往页面发起域以外的域的请求中,如果服务不允许该域,则调用将失败。
“不安全”请求,例如 POST、PUT 或 DELETE,不能以同样的方式完成。如果服务不支持 CORS,它将忽略“Origin”标头并接受请求,可能会产生副作用(例如,删除记录),并且在客户端收到响应时,浏览器仍然可以“失败”的请求,但损害已经造成。在这些情况下,浏览器所做的是首先发送一个预检请求,这是一个 HTTP OPTIONS 请求,请求允许发送实际请求。如果服务响应了允许调用的请求,那么只有浏览器才会将用户请求发送到服务。
【讨论】:
以上是关于预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400的主要内容,如果未能解决你的问题,请参考以下文章
从 JavaScript 访问 WCF WebService - 对预检请求的响应未通过访问控制检查
在带有 Wcf 服务的 Angular JS 的预检响应中,Access-Control-Allow-Methods 不允许方法 PUT
WCF 413 请求实体太大 - 自托管 WebHttpBinding