zoukankan      html  css  js  c++  java
  • WCF REST开启Cors 解决 No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 405.

    现象:

    编写了REST接口:

    [ServiceContract]
    public interface IService1
    {
    
        [OperationContract]
        [WebInvoke(UriTemplate = "/TestMethod", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json
          )]
        string TestMethod(CompositeType value);
    
    }
      

    数据契约

    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";
    
        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }
    
        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }  

    服务实现

    public class Service1 : IService1
    
    {
        public string TestMethod(CompositeType value)
        {
            return string.Format("You entered: {0}", value.StringValue);
        }
    }
    

     

    ajax调用

    $(document).ready(function () {
    	$("button").click(function () {
    		alert("clicked");
    		var data = $("#txt").val();
    		var postdata = {};
    		var data_obj = {"BoolValue" : "true" , "StringValue": data}
    		postdata["value"] =  data_obj; 
    
    		var url = "https://tmdev01.tm00.com/testwcf/service1.svc/TestMethod";
    		$.ajax({
    			type: "POST",
    			url: url,
    			contentType: "application/json; charset=utf-8",
    			data: JSON.stringify(postdata),
    			dataType: "json",
    			success: function(data) {console.log(data);},
    			error: function(a,b,c) {console.log(a);}
    		});
    	});
    });
      

    报错:

    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 405.
    

      

    方法1:

    全局请求拦截,处理OPTION谓词

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
    
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }
    }  

    方法2:

    定义跨域资源共享相关常量

    class CorsConstants
    {
           internal const string Origin = "Origin";
           internal const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
           internal const string AccessControlRequestMethod = "Access-Control-Request-Method";
           internal const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
           internal const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
           internal const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
           internal const string PreflightSuffix = "_preflight_";
    }
    

      

    创建cors属性

    public class CorsEnabledAttribute : Attribute, IOperationBehavior
    {
           public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
           {
           }
    
           public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
           {
           }
    
           public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
           {
           }
    
           public void Validate(OperationDescription operationDescription)
           {
           }
    }
    

    创建自定义消息分发拦截器

    class CorsEnabledMessageInspector : IDispatchMessageInspector
        {
            private List corsEnabledOperationNames;
    
            public CorsEnabledMessageInspector(List corsEnabledOperations)
            {
                this.corsEnabledOperationNames = corsEnabledOperations.Select(o => o.Name).ToList();
            }
    
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                HttpRequestMessageProperty httpProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                object operationName;
                request.Properties.TryGetValue(WebHttpDispatchOperationSelector.HttpOperationNamePropertyName, out operationName);
                if (httpProp != null && operationName != null && this.corsEnabledOperationNames.Contains((string)operationName))
                {
                    string origin = httpProp.Headers[CorsConstants.Origin];
                    if (origin != null)
                    {
                        return origin;
                    }
                }
    
                return null;
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                string origin = correlationState as string;
                if (origin != null)
                {
                    HttpResponseMessageProperty httpProp = null;
                    if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
                    {
                        httpProp = (HttpResponseMessageProperty)reply.Properties[HttpResponseMessageProperty.Name];
                    }
                    else
                    {
                        httpProp = new HttpResponseMessageProperty();
                        reply.Properties.Add(HttpResponseMessageProperty.Name, httpProp);
                    }
    
                    httpProp.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                }
            }
        } 
    

     

    class EnableCorsEndpointBehavior : IEndpointBehavior
        {
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                List corsEnabledOperations = endpoint.Contract.Operations
                    .Where(o => o.Behaviors.Find() != null)
                    .ToList();
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CorsEnabledMessageInspector(corsEnabledOperations));
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
            }
        }
    

      

    class PreflightOperationBehavior : IOperationBehavior
        {
            private OperationDescription preflightOperation;
            private List allowedMethods;
    
            public PreflightOperationBehavior(OperationDescription preflightOperation)
            {
                this.preflightOperation = preflightOperation;
                this.allowedMethods = new List();
            }
    
            public void AddAllowedMethod(string httpMethod)
            {
                this.allowedMethods.Add(httpMethod);
            }
    
            public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
            {
            }
    
            public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
            {
            }
    
            public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
            {
                dispatchOperation.Invoker = new PreflightOperationInvoker(operationDescription.Messages[1].Action, this.allowedMethods);
            }
    
            public void Validate(OperationDescription operationDescription)
            {
            }
        } 
    

      

    class PreflightOperationInvoker : IOperationInvoker
        {
            private string replyAction;
            List allowedHttpMethods;
    
            public PreflightOperationInvoker(string replyAction, List allowedHttpMethods)
            {
                this.replyAction = replyAction;
                this.allowedHttpMethods = allowedHttpMethods;
            }
    
            public object[] AllocateInputs()
            {
                return new object[1];
            }
    
            public object Invoke(object instance, object[] inputs, out object[] outputs)
            {
                Message input = (Message)inputs[0];
                outputs = null;
                return HandlePreflight(input);
            }
    
            public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
            {
                throw new NotSupportedException("Only synchronous invocation");
            }
    
            public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
            {
                throw new NotSupportedException("Only synchronous invocation");
            }
    
            public bool IsSynchronous
            {
                get { return true; }
            }
    
            Message HandlePreflight(Message input)
            {
                HttpRequestMessageProperty httpRequest = (HttpRequestMessageProperty)input.Properties[HttpRequestMessageProperty.Name];
                string origin = httpRequest.Headers[CorsConstants.Origin];
                string requestMethod = httpRequest.Headers[CorsConstants.AccessControlRequestMethod];
                string requestHeaders = httpRequest.Headers[CorsConstants.AccessControlRequestHeaders];
    
                Message reply = Message.CreateMessage(MessageVersion.None, replyAction);
                HttpResponseMessageProperty httpResponse = new HttpResponseMessageProperty();
                reply.Properties.Add(HttpResponseMessageProperty.Name, httpResponse);
    
                httpResponse.SuppressEntityBody = true;
                httpResponse.StatusCode = HttpStatusCode.OK;
                if (origin != null)
                {
                    httpResponse.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                }
    
                if (requestMethod != null && this.allowedHttpMethods.Contains(requestMethod))
                {
                    httpResponse.Headers.Add(CorsConstants.AccessControlAllowMethods, string.Join(",", this.allowedHttpMethods));
                }
    
                if (requestHeaders != null)
                {
                    httpResponse.Headers.Add(CorsConstants.AccessControlAllowHeaders, requestHeaders);
                }
    
                return reply;
            }
        }
    

      

    给接口增加 cors属性标记

    [ServiceContract]
    public interface IService1
    {
    
        [OperationContract]
        [WebInvoke(UriTemplate = "/TestMethod", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json
          ),CorsEnabled]
        string TestMethod(CompositeType value);
    
    }
    

      

    CORS详细说明:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

     

      

  • 相关阅读:
    Java自定义注解(1)
    SpringMvc入门
    Nginx服务器简单配置
    EL和JSTL使用笔记
    JQuery笔记
    Java05 JDBC介绍及基本操作
    Java04 线程同步问题解决——线程锁(同步锁、互斥锁)
    web服务、正向代理、反向代理的一点理解
    java03 IO操作
    Docker05 Docker容器
  • 原文地址:https://www.cnblogs.com/nodegis/p/9770583.html
Copyright © 2011-2022 走看看