Adding Custom WCF header to Endpoint Programatically for Reliable Sessions

吃可爱长大的小学妹 提交于 2019-12-13 14:01:03

问题


I'm building a WCF router and my client uses Reliable Sessions. In this scenario when the client opens a channel a message is sent (establishing a Reliable Session?). Its contents is as follows:

<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>

The problem here is that the headers do not contain any information I can use to look up what service to route the message to. In Busatmante's router sample code she gets around this by adding a header to the endpoint:

  <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>

When the reliable session is opened the message contains this custom header.

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

This is great; however, I have a requirement to configure the client programatically. I figured that the ChannelFactory Endpoint would have a Header object to which I could manually add my custom header. Unfortunately it does not. So I did some searching and found some recomendations to extend WCF by implementing an IClientMessageInspector to add my header and adding it as a behavior to my endpoint.

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
}

So when my client makes a service call the message contains the custom header but the message establishing the Reliable Sessions still does not.

So my question is; how do I add a custom header to the Endpoint programatically in such a way that the reliable session message contains it?

Many Thanks


回答1:


Figured it out. Although there is no property or method to add a header to an EndpointAddress there is an optional parameter on the constructor.

_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);

Now when I receive the message establishing the reliable session it actually does contain my custom header. This kinda makes sense as the message inspector most likely only operates on dispatched messages while the message establishing the reliable session is generated by lower level WCF code.




回答2:


This works for me

   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);
        }
    }



回答3:


To programmatically add address headers see MSDN's Address Headers where one can programmatically add a header such as:

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


来源:https://stackoverflow.com/questions/3152056/adding-custom-wcf-header-to-endpoint-programatically-for-reliable-sessions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!