Cross Origin Resource Sharing for c# WCF Restful web service hosted as Windows service

前端 未结 2 812
灰色年华
灰色年华 2020-12-03 09:00

I have a WCF Restful service which I am hosting as Windows service. I want to add cross domain support to my service. However, i can do this easily when I use global.asax fi

2条回答
  •  暖寄归人
    2020-12-03 09:40

    Finally found a solution to my queries.

    Its all here. Supporting Cross Origin Resource

    Nice step by step explanation. I guess I could have never figured this out on my own.

    CODE:

    Create 2 classes as follows:

    1. MessageInspector implementing IDispatchMessageInspector.
    2. BehaviorAttribute implementing Attribute, IEndpointBehavior and IOperationBehavior.

    With the following details:

    //MessageInspector Class
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;
    using System.ServiceModel.Description;
    namespace myCorsService
    {
      public class MessageInspector  : IDispatchMessageInspector
      {
        private ServiceEndpoint _serviceEndpoint;
    
        public MessageInspector(ServiceEndpoint serviceEndpoint)
        {
          _serviceEndpoint = serviceEndpoint;
        }
    
        /// 
        /// Called when an inbound message been received
        /// 
        /// The request message.
        /// The incoming channel.
        /// The current service instance.
        /// 
        /// The object used to correlate stateMsg. 
        /// This object is passed back in the method.
        /// 
        public object AfterReceiveRequest(ref Message request, 
                                              IClientChannel channel, 
                                              InstanceContext instanceContext)
        {
          StateMessage stateMsg = null;
          HttpRequestMessageProperty requestProperty = null;
          if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
          {
            requestProperty = request.Properties[HttpRequestMessageProperty.Name]
                              as HttpRequestMessageProperty;
          }
    
          if (requestProperty != null)
          {
            var origin = requestProperty.Headers["Origin"];
            if (!string.IsNullOrEmpty(origin))
            {
              stateMsg = new StateMessage();
              // if a cors options request (preflight) is detected, 
              // we create our own reply message and don't invoke any 
              // operation at all.
              if (requestProperty.Method == "OPTIONS")
              {
                stateMsg.Message = Message.CreateMessage(request.Version, null);
              }
              request.Properties.Add("CrossOriginResourceSharingState", stateMsg);
            }
          }
    
          return stateMsg;
        }
    
        /// 
        /// Called after the operation has returned but before the reply message
        /// is sent.
        /// 
        /// The reply message. This value is null if the 
        /// operation is one way.
        /// The correlation object returned from
        ///  the method.
        public void BeforeSendReply(ref  Message reply, object correlationState)
        {
          var stateMsg = correlationState as StateMessage;
    
          if (stateMsg != null)
          {
            if (stateMsg.Message != null)
            {
              reply = stateMsg.Message;
            }
    
            HttpResponseMessageProperty responseProperty = null;
    
            if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
            {
              responseProperty = reply.Properties[HttpResponseMessageProperty.Name]
                                 as HttpResponseMessageProperty;
            }
    
            if (responseProperty == null)
            {
              responseProperty = new HttpResponseMessageProperty();
              reply.Properties.Add(HttpResponseMessageProperty.Name,
                                   responseProperty);
            }
    
            // Access-Control-Allow-Origin should be added for all cors responses
            responseProperty.Headers.Set("Access-Control-Allow-Origin", "*");
    
            if (stateMsg.Message != null)
            {
              // the following headers should only be added for OPTIONS requests
              responseProperty.Headers.Set("Access-Control-Allow-Methods",
                                           "POST, OPTIONS, GET");
              responseProperty.Headers.Set("Access-Control-Allow-Headers",
                        "Content-Type, Accept, Authorization, x-requested-with");
            }
          }
        }
      }
    
      class StateMessage
      {
        public Message Message;
      }
    }
    
    //BehaviorAttribute Class
    using System;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace OpenBetRetail.NFCReaderService
    {
      public class BehaviorAttribute : Attribute, IEndpointBehavior,
                                     IOperationBehavior
      {        
        public void Validate(ServiceEndpoint endpoint) { }
    
        public void AddBindingParameters(ServiceEndpoint endpoint,
                                 BindingParameterCollection bindingParameters) { }
    
        /// 
        /// This service modify or extend the service across an endpoint.
        /// 
        /// The endpoint that exposes the contract.
        /// The endpoint dispatcher to be
        /// modified or extended.
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
                                          EndpointDispatcher endpointDispatcher)
        {
          // add inspector which detects cross origin requests
          endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
                                                 new MessageInspector(endpoint));
        }
    
       public void ApplyClientBehavior(ServiceEndpoint endpoint,
                                       ClientRuntime clientRuntime) { }
    
       public void Validate(OperationDescription operationDescription) { }
    
       public void ApplyDispatchBehavior(OperationDescription operationDescription,
                                         DispatchOperation dispatchOperation) { }
    
       public void ApplyClientBehavior(OperationDescription operationDescription,
                                       ClientOperation clientOperation) { }
    
       public void AddBindingParameters(OperationDescription operationDescription,
                                 BindingParameterCollection bindingParameters) { }
    
      }
    }
    

    After this all you need to do is add this message inspector to service end point behavior.

    ServiceHost host = new ServiceHost(typeof(myService), _baseAddress);
    foreach (ServiceEndpoint EP in host.Description.Endpoints)
                EP.Behaviors.Add(new BehaviorAttribute());
    

    Thanks guys for your help.

提交回复
热议问题