C# 将WCF CORS restful服务从.Net 4.5转换为3.5会导致飞行前请求中断
我有一个WCF服务,使用CORS托管在控制台应用程序上,该应用程序在.NET4.5中运行良好。该应用程序现在需要在.NET3.5中工作,而对于任何POST请求,飞行前选项请求现在都失败 以下是服务的接口:C# 将WCF CORS restful服务从.Net 4.5转换为3.5会导致飞行前请求中断,c#,.net,wcf,rest,C#,.net,Wcf,Rest,我有一个WCF服务,使用CORS托管在控制台应用程序上,该应用程序在.NET4.5中运行良好。该应用程序现在需要在.NET3.5中工作,而对于任何POST请求,飞行前选项请求现在都失败 以下是服务的接口: [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle =
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
BiometricCaptureResponse Start(BiometricCaptureRequest biometricRequest);
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void Options();
实际服务:
public BiometricCaptureResponse Start(BiometricCaptureRequest biometricRequest)
{
//Stuff and things
}
public void Options()
{
return;
}
应用于请求和响应的COR的行为
public string clientOrigin;
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
HttpRequestMessageProperty requestProperty = request.Properties[HttpRequestMessageProperty.Name]
as HttpRequestMessageProperty;
if (requestProperty != null && requestProperty.Headers.AllKeys.Contains("Origin") && !string.IsNullOrEmpty(requestProperty.Headers["Origin"]))
{
clientOrigin = requestProperty.Headers["Origin"];
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
HttpResponseMessageProperty httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
if (httpHeader != null)
{
httpHeader.ApplyCrossOriginSupport(clientOrigin);
}
}
public static void ApplyCrossOriginSupport(this HttpResponseMessageProperty message, string origin)
{
message.Headers.Add("Access-Control-Allow-Origin", origin);
message.Headers.Add("Access-Control-Allow-Method", ConfigurationManager.AppSettings["Access-Control-Allow-Method"]);
message.Headers.Add("Access-Control-Allow-Headers", ConfigurationManager.AppSettings["Access-Control-Allow-Headers"]);
}
这在4.5中都起到了作用,这是将要发生的过程:
OPTIONS http://localhost:8502/testservice.svc/rest/Start net::ERR_CONNECTION_RESET
这可能与WebInvoke属性有关吗?它的MSDN页面将其描述为4.5/3.5客户端技术,而我只使用.NET3.5
更新:
将选项服务的以下属性更改为使用所有方法
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
[WebInvoke(Method = "*", UriTemplate = "*")]
允许选项请求命中服务,应用程序可以像这样工作,但这仍然不是最佳解决方案,因为它不是特定于选项请求,这背后有什么原因?我担心.Net 3.5版本的WebHttpDispatchOperationSelector中有一个小错误 选择器无法识别与*UriTemplate组合的方法选项 作为一种解决方法,您可以使用自定义版本替换默认WebHttpBehavior
public class CorsWebHttpDispatchOperationSelector : WebHttpDispatchOperationSelector
{
private WebHttpDispatchOperationSelector target;
private ServiceEndpoint endpoint;
OperationDescription optionOperation;
public CorsWebHttpDispatchOperationSelector(ServiceEndpoint endpoint, WebHttpDispatchOperationSelector target)
{
this.target = target;
this.endpoint = endpoint;
foreach (var item in this.endpoint.Contract.Operations) {
var webInvoke = item.Behaviors.OfType<WebInvokeAttribute>().FirstOrDefault();
if (webInvoke != null && webInvoke.Method.Equals("options",StringComparison.OrdinalIgnoreCase) && webInvoke.UriTemplate == "*") {
optionOperation = item;
break;
}
}
}
#region IDispatchOperationSelector Members
protected override string SelectOperation(ref Message message, out bool uriMatched)
{
var result = target.SelectOperation(ref message);
var matched = message.Properties["UriMatched"] as bool?;
message.Properties.Remove("UriMatched");
message.Properties.Remove("HttpOperationName");
uriMatched = matched.HasValue && matched.Value;
var httpRequest = message.Properties["httpRequest"] as HttpRequestMessageProperty;
var cond = string.IsNullOrEmpty(result) &&
httpRequest != null &&
httpRequest.Method.Equals("options",StringComparison.OrdinalIgnoreCase);
if (cond && optionOperation != null) {
result = optionOperation.Name;
uriMatched = true;
}
return result;
}
#endregion
}
public class CorsWebHttpBehavior : WebHttpBehavior {
protected override WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
{
return new CorsWebHttpDispatchOperationSelector(endpoint, base.GetOperationSelector(endpoint));
}
}
公共类CorsWebHttpDispatchOperationSelector:WebHttpDispatchOperationSelector
{
私有WebHttpDispatchOperationSelector目标;
私有服务端点;
操作说明选项操作;
public CorsWebHttpDispatchOperationSelector(ServiceEndpoint端点,WebHttpDispatchOperationSelector目标)
{
this.target=目标;
this.endpoint=端点;
foreach(此.endpoint.Contract.Operations中的var项){
var webInvoke=item.Behaviors.OfType().FirstOrDefault();
if(webInvoke!=null&&webInvoke.Method.Equals(“选项”,StringComparison.OrdinalIgnoreCase)&&webInvoke.UriTemplate==“*”){
optionOperation=项目;
打破
}
}
}
#地区选举委员
受保护的覆盖字符串选择操作(ref消息,out bool URIMATTED)
{
var结果=目标。选择操作(参考消息);
var matched=message.Properties[“UriMatched”]作为bool?;
message.Properties.Remove(“UriMatched”);
message.Properties.Remove(“HttpOperationName”);
uriMatched=matched.HasValue&&matched.Value;
var httpRequest=message.Properties[“httpRequest”]作为HttpRequestMessageProperty;
var cond=string.IsNullOrEmpty(结果)和
httpRequest!=null&&
httpRequest.Method.Equals(“选项”,StringComparison.OrdinalIgnoreCase);
if(cond&&optionOperation!=null){
结果=optionOperation.Name;
URIMATTED=true;
}
返回结果;
}
#端区
}
公共类CorsWebHttpBehavior:WebHttpBehavior{
受保护的覆盖WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint)
{
返回新的CorsWebHttpDispatchOperationSelector(endpoint,base.GetOperationSelector(endpoint));
}
}
你在3.5中遇到的错误是什么?@peer将错误添加到问题的底部。谢谢,这比使用*来概括一切要好得多,你怎么知道这是.Net 3.5中的一个错误?@richardmac好吧,它可能是一个错误,也可能根本不受支持。WebHttpDispatchOperationSelector的代码与.net 3.5到.net 4.0略有不同。当您在我对SelectOperation方法的重写上放置断点时,您将看到target.SelectOperation(ref消息)在针对4.5构建时为您提供有效结果,而在针对3.5构建时,end为空