C# - 自托管服务 - POST 请求 - CORS 错误

问题描述 投票:0回答:1

我有 WCF 自托管服务来与本地连接的打印机通信以打印徽章。我们基于浏览器的应用程序调用本地服务来打印徽章。所有 GET 调用都工作正常,但 POST 请求总是给出 CORS 错误。

获取呼叫(工作正常)

POST 调用 - 因 CORS 错误而失败,飞行前请求正常

C# 代码


 private void startService_HTTPS(System.Diagnostics.EventLog eventLog)
        {
            eventLog.WriteEntry("Begin startService.......");
            string serviceUrl = Config.protocol_https + "://" + Config.host + ":" + Config.portNumber_https;
            WebServiceHost webServiceHost = new WebServiceHost(typeof(Service), new Uri(serviceUrl));
            try
            {
                ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
            
                KeyedByTypeCollection<IServiceBehavior> behaviors = webServiceHost.Description.Behaviors;
                ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior()
                {
                    HttpGetEnabled = false,
                    HttpsGetEnabled = true
                    
                };
                behaviors.Add(serviceMetadataBehavior);
                ServiceDebugBehavior serviceDebugBehavior = webServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
                if (serviceDebugBehavior == null)
                {
                    webServiceHost.Description.Behaviors.Add(new ServiceDebugBehavior()
                    {
                        IncludeExceptionDetailInFaults = true
                    });
                }
                else
                {
                    serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
                }
                WebHttpBinding webHttpBinding = new WebHttpBinding(WebHttpSecurityMode.Transport)
                {
                    HostNameComparisonMode = HostNameComparisonMode.Exact,
                    MaxReceivedMessageSize = (long)2147483647,
                    TransferMode = TransferMode.Streamed,
                   // CrossDomainScriptAccessEnabled = true
                };
                ServiceEndpoint serviceEndpoint = webServiceHost.AddServiceEndpoint(typeof(IService), webHttpBinding, serviceUrl);
                serviceEndpoint.Behaviors.Add(new WebHttpBehavior());
                  serviceEndpoint.Behaviors.Add(new EnableCrossOriginResourceSharingBehavior());

              
                webServiceHost.Open();
                eventLog.WriteEntry("Started HTTPS services successfully......"+serviceUrl);

              //  CertManager certs = new CertManager();
               // certs.setupCerts(eventLog);
                
            }
            catch (CommunicationException cex)
            {
                Console.WriteLine("An exception occurred: {0}", cex.Message);
                eventLog.WriteEntry("Exception "+cex.Message);
                eventLog.WriteEntry(cex.StackTrace);
                webServiceHost.Abort();
            }
        }


C# 自定义行为代码

public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            var requiredHeaders = new Dictionary<string, string>();

            requiredHeaders.Add("Access-Control-Allow-Origin", "*");
            requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
            requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");

            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }

        public override Type BehaviorType
        {
            get { return typeof(EnableCrossOriginResourceSharingBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new EnableCrossOriginResourceSharingBehavior();
        }
    }
public class CustomHeaderMessageInspector : IDispatchMessageInspector
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        Dictionary<string, string> requiredHeaders;
        public CustomHeaderMessageInspector(Dictionary<string, string> headers)
        {
            requiredHeaders = headers ?? new Dictionary<string, string>();
        }

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            return null;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            var httpHeader = reply.Properties["httpResponse"] as System.ServiceModel.Channels.HttpResponseMessageProperty;
            httpHeader.StatusCode = System.Net.HttpStatusCode.OK;

            foreach (var item in requiredHeaders)
            {
                log.Debug("BeforeSendReply add header " + item.Key + ", val " + item.Value);

                httpHeader.Headers.Add(item.Key, item.Value);
            }
        }
    }

我在这里寻求帮助......

我尝试向服务添加自定义行为,但总是失败,正在寻求一些帮助来解决此问题。

c# wcf cors self-host-webapi
1个回答
0
投票

我不认为你可以使用 endpointDispatcher.DispatchRuntime.MessageInspectors.Add 来配置Cros策略。它是一种在服务端点或客户端回调端点的运行时行为中插入、修改或扩展自定义消息检查器的方法。

我的建议:

1.新建一个Global.asax文件

2.添加代码

protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://127.0.0.1:47756");
    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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.