Asp.net

作為 Windows 服務託管的 c# WCF Restful Web 服務的跨源資源共享

  • July 2, 2021

我有一個作為 Windows 服務託管的 WCF Restful 服務。我想為我的服務添加跨域支持。但是,當我使用 global.asax 文件時,我可以輕鬆地做到這一點。但我想將我的服務託管為 Windows 服務。

我創建了一個項目,將我的服務託管為 Windows 服務。現在我面臨的問題是,我現在無法添加跨域支持。我嘗試了通過 app.config 文件找到的所有可能的解決方案,但沒有一個可行。我在這些連結上嘗試了解決方案:

點網技巧

enable-cors.org

我嘗試通過在每個服務契約方法中呼叫以下函式來設置程式碼中的標頭。

private static void SetResponseHeader()
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache, no-store");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Request-Methods", "GET, POST, PUT, DELETE, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");
}

界面:

namespace ReaderService
{
[ServiceContract]
public interface INFCReader
{
   [OperationContract]
   [WebInvoke(UriTemplate = "GetLogin", Method = "POST")]
   GetLoginResults GetLogin(DisplayRequest dispRequest);
}

這裡 DisplayRequest 是一個類。

請幫助各位。讓我知道是否有人想查看任何其他程式碼。

非常感謝。

編輯:::::::

非常感謝托馬斯的回复。我創建了一個實現 IDispactchMessageInspector 的類 MessageInspector。我在 MessageInspector 類中有以下程式碼。

public class MessageInspector : IDispatchMessageInspector
{
   public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
   {
       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
       if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
       {
           HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
           HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
           HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
           HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
           HttpContext.Current.Response.End();
       }
       return null;
   }
}

我現在得到的錯誤是——“對象引用未設置為對象的實例。” 錯誤在上述程式碼的這一行

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

我要做的就是為我的 Web 服務添加 CORS 支持。如果我做得正確,請告訴我。或者有沒有其他方法可以做到這一點。

終於找到了我的查詢的解決方案。

都在這裡。支持跨域資源

很好的一步一步的解釋。我想我自己永遠也想不通。

程式碼:

創建 2 個類,如下所示:

  1. MessageInspector實施IDispatchMessageInspector.
  2. BehaviorAttribute實施Attribute,IEndpointBehaviorIOperationBehavior.

帶有以下詳細資訊:

//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) { }

 }
}

在此之後,您需要做的就是將此消息檢查器添加到服務端點行為。

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

謝謝大家幫助。

引用自:https://stackoverflow.com/questions/16024347