9

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 はクラスです。

みんな助けてください。誰かが他のコードを見たい場合はお知らせください。

どうもありがとう。

編集:::::::

トーマスさん、お返事ありがとうございます。IDispatchMessageInspector を実装するクラス 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 サポートを追加することだけです。私が正しくやっているかどうか教えてください。または、同じことを行う他の方法があります。

4

2 に答える 2

17

最後に、私のクエリに対する解決策を見つけました。

そのすべてがここにあります。クロスオリジン リソースのサポート

親切なステップバイステップの説明。これは自分一人では絶対に思いつかなかったと思います。

コード:

次のように 2 つのクラスを作成します。

  1. MessageInspector実施中IDispatchMessageInspector
  2. BehaviorAttribute実装AttributeIEndpointBehaviorおよびIOperationBehavior

詳細は次のとおりです。

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

助けてくれてありがとう。

于 2013-04-16T14:38:39.663 に答える