Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将WCF CORS restful服务从.Net 4.5转换为3.5会导致飞行前请求中断_C#_.net_Wcf_Rest - Fatal编程技术网

C# 将WCF CORS restful服务从.Net 4.5转换为3.5会导致飞行前请求中断

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 =

我有一个WCF服务,使用CORS托管在控制台应用程序上,该应用程序在.NET4.5中运行良好。该应用程序现在需要在.NET3.5中工作,而对于任何POST请求,飞行前选项请求现在都失败

以下是服务的接口:

    [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中都起到了作用,这是将要发生的过程:

  • 后受托人要求
  • 选项()服务命中率
  • BeforeSendReply()
  • 后受托人要求
  • 开始()
  • BeforeSendReply()
  • 现在在3.5中,Ooptions服务将不会被命中,这将导致整个请求失败,我是否缺少任何东西来让它在3.5中工作

    我从Chrome控制台得到的错误是:

    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为空