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

前端 未结 2 798
灰色年华
灰色年华 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:37

    I believe that the closest thing to Application_BeginRequest in the WCF world are Message Inspectors:

    A message inspector is an extensibility object that can be used in the service model's client runtime and dispatch runtime programmatically or through configuration and that can inspect and alter messages after they are received or before they are sent.

    In order to use custom message inspectors you'll have to:

    1. Create a class that implements the IDispatchMessageInspector interface (your custom inspector)
    2. Add the custom inspector to your service's DispatchRuntime.MessageInspectors collection

    Here you can find more info and some sample code on how to do this.

    0 讨论(0)
  • 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;
        }
    
        /// <summary>
        /// Called when an inbound message been received
        /// </summary>
        /// <param name="request">The request message.</param>
        /// <param name="channel">The incoming channel.</param>
        /// <param name="instanceContext">The current service instance.</param>
        /// <returns>
        /// The object used to correlate stateMsg. 
        /// This object is passed back in the method.
        /// </returns>
        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;
        }
    
        /// <summary>
        /// Called after the operation has returned but before the reply message
        /// is sent.
        /// </summary>
        /// <param name="reply">The reply message. This value is null if the 
        /// operation is one way.</param>
        /// <param name="correlationState">The correlation object returned from
        ///  the method.</param>
        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) { }
    
        /// <summary>
        /// This service modify or extend the service across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that exposes the contract.</param>
        /// <param name="endpointDispatcher">The endpoint dispatcher to be
        /// modified or extended.</param>
        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.

    0 讨论(0)
提交回复
热议问题