3

私は WCF ルーターを構築しており、クライアントは Reliable Sessions を使用しています。このシナリオでは、クライアントがチャネルを開くと、メッセージが送信されます (信頼できるセッションを確立しますか?)。その内容は次のとおりです。

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-rx/wsrm/200702/CreateSequence</a:Action>
    <a:MessageID>urn:uuid:1758f794-c5d3-4573-b252-7a07344cc257</a:MessageID>
    <a:To s:mustUnderstand="1">http://localhost:8010/RouterService</a:To>
  </s:Header>
  <s:Body>
    <CreateSequence xmlns="http://docs.oasis-open.org/ws-rx/wsrm/200702">
      <AcksTo>
        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
      </AcksTo>
      <Offer>
        <Identifier>urn:uuid:64a12658-71d9-4967-88ec-9bb0610f7ecb</Identifier>
        <Endpoint>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </Endpoint>
        <IncompleteSequenceBehavior>DiscardFollowingFirstGap</IncompleteSequenceBehavior>
      </Offer>
    </CreateSequence>
  </s:Body>
</s:Envelope>

ここでの問題は、メッセージをルーティングするサービスを検索するために使用できる情報がヘッダーに含まれていないことです。Busatmante のルーター サンプル コードでは、エンドポイントにヘッダーを追加することでこれを回避しています。

  <client>
    <endpoint address="http://localhost:8010/RouterService" binding="ws2007HttpBinding"
      bindingConfiguration="wsHttp"
      contract="localhost.IMessageManagerService" >
      <headers>
        <Route xmlns="http://www.thatindigogirl.com/samples/2008/01" >http://www.thatindigogirl.com/samples/2008/01/IMessageManagerService</Route>
      </headers>
    </endpoint>
  </client>

信頼できるセッションが開かれると、メッセージにこのカスタム ヘッダーが含まれます。

<Route a:IsReferenceParameter="true" xmlns="http://www.thatindigogirl.com/samples/2008/01">http://www.thatindigogirl.com/samples/2008/01/IMessageManagerService</Route>

これは素晴らしい; ただし、クライアントをプログラムで構成する必要があります。ChannelFactory エンドポイントには、カスタム ヘッダーを手動で追加できる Header オブジェクトがあると考えました。残念ながらそうではありません。そのため、検索を行ったところ、IClientMessageInspector を実装してヘッダーを追加し、それを動作としてエンドポイントに追加することで、WCF を拡張するためのいくつかの推奨事項が見つかりました。

public class ContractNameMessageInspector : IClientMessageInspector {

    private const string HEADER_NAME = "ContractName";
    private readonly string _ContractName;

    public ContractNameMessageInspector(string contractName) {
        _ContractName = contractName;
    }

    #region IClientMessageInspector Members

    public void AfterReceiveReply(ref Message reply, object correlationState) { }

    public object BeforeSendRequest(ref Message request, IClientChannel channel) {

        HttpRequestMessageProperty httpRequestMessage;
        object httpRequestMessageObject;

        if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject)) {
            httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
            if (httpRequestMessage != null && string.IsNullOrEmpty(httpRequestMessage.Headers[HEADER_NAME])) {
                httpRequestMessage.Headers[HEADER_NAME] = this._ContractName;
            }
        }
        else {
            httpRequestMessage = new HttpRequestMessageProperty();
            httpRequestMessage.Headers.Add(HEADER_NAME, this._ContractName);
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
        }
        return null;
    }

    #endregion
}

そのため、クライアントがサービス呼び出しを行うと、メッセージにはカスタム ヘッダーが含まれますが、信頼できるセッションを確立するメッセージには含まれません。

私の質問は次のとおりです。信頼できるセッション メッセージにカスタム ヘッダーが含まれるように、カスタム ヘッダーをエンドポイントにプログラムで追加するにはどうすればよいですか?

どうもありがとう

4

3 に答える 3

5

理解した。EndpointAddressにヘッダーを追加するためのプロパティやメソッドはありませんが、コンストラクターにはオプションのパラメーターがあります。

_Binding = bindingFactory.GetBinding(serviceUri, typeof(T));
AddressHeader header = AddressHeader.CreateAddressHeader("ContractName", "NameSpace", typeof (T).ToString());

_Address = new EndpointAddress(serviceUri, header);
_ChannelFactory = new ChannelFactory<T>(_Binding, _Address);

これで、信頼できるセッションを確立するメッセージを受信すると、実際にはカスタムヘッダーが含まれています。信頼できるセッションを確立するメッセージが低レベルのWCFコードによって生成されている間、メッセージインスペクターはディスパッチされたメッセージに対してのみ動作する可能性が高いため、これはちょっと意味があります。

于 2010-07-02T23:23:58.800 に答える
1

これは私のために働く

   public TResult Invoke<TResult>(Func<TClient, TResult> func,MessageHeader header)
    {
        TClient client = default(TClient);
        var sw = new Stopwatch();
        try
        {
            sw.Start();
            using (client = _channelFactory.CreateChannel())
            {
               using (OperationContextScope contextScope = new OperationContextScope(client))
                {
                    OperationContext.Current.OutgoingMessageHeaders.Add(header);

                    return func.Invoke(client);
                }
            }
        }
        finally
        {
            CloseConnection(client);
            Instrument(this.GetType().Name, sw);
        }
    }
于 2016-09-01T05:04:02.570 に答える
0

プログラムでアドレス ヘッダーを追加するには、次のようなヘッダーをプログラムで追加できるMSDN のアドレス ヘッダーを参照してください。

var cl = new MyWCFClientContext();

var eab = new EndpointAddressBuilder(cl.Endpoint.Address);

eab.Headers.Add( AddressHeader.CreateAddressHeader("ClientIdentification", // Header Key
                                                    string.Empty,           // Namespace
                                                    "JabberwockyClient"));  // Header Value

cl.Endpoint.Address = eab.ToEndpointAddress();
于 2014-03-31T16:34:48.983 に答える