C# - SelfHosted Service - POST request - CORS Error

38 Views Asked by At

I have WCF Selfhosted service to communicate with local connected printer to print badges. Our browser based application calls local service to print badges. All GET calls perfectly working fine, but POST request always giving CORS error.

GET Call (Works fine)

enter image description here

POST Call - Fails with CORS error, Pre-Flight request is good

enter image description here

enter image description here

C# Code


 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# Custom behavior code

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);
            }
        }
    }

I am looking for some help here....

I tried adding custom behaviors to service, but its always failing, looking for some help in resolving this issue.

1

There are 1 best solutions below

0
QI You On

I don't think it's okay for you to use endpointDispatcher.DispatchRuntime.MessageInspectors.Add to configure Cros policies. It is a method for inserting, modifying, or extending a custom message inspector in the runtime behavior of a service endpoint or a client callback endpoint.

My suggestion:

1.Create a new Global.asax file

enter image description here

2.Add code

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();
    }
}