2010-06-30 3 views
3

Je construis un routeur WCF et mon client utilise des sessions fiables. Dans ce scénario lorsque le client ouvre un canal, un message est envoyé (établissement d'une session fiable?). Son contenu est le suivant:Ajout d'un en-tête WCF personnalisé à un point de terminaison programmé pour des sessions fiables

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

Le problème ici est que les en-têtes ne contiennent pas d'informations que je peux utiliser pour regarder ce service pour acheminer le message. Dans l'exemple de code routeur Busatmante elle se déplace en ajoutant un en-tête à l'extrémité:

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

Lorsque la session fiable est ouvert le message contient cet en-tête personnalisé.

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

C'est génial; Cependant, j'ai besoin de configurer le client par programmation. J'ai pensé que le point de terminaison ChannelFactory aurait un objet Header auquel je pourrais ajouter manuellement mon en-tête personnalisé. Malheureusement, ce n'est pas le cas. J'ai donc fait quelques recherches et trouvé quelques recommandations pour étendre WCF en implémentant un IClientMessageInspector pour ajouter mon en-tête et l'ajouter comme un comportement à mon point de terminaison.

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 
} 

Alors, quand mon client fait un appel de service le message contient l'en-tête personnalisé, mais le message établissant les sessions fiables ne fait toujours pas.

Donc, ma question est; Comment puis-je ajouter un en-tête personnalisé au point de terminaison de manière à ce que le message de session fiable le contienne?

Nombreux remerciements

Répondre

4

Compris. Bien qu'il n'y ait aucune propriété ou méthode pour ajouter un en-tête à une EndpointAddress, il existe un paramètre facultatif sur le constructeur. Maintenant, lorsque je reçois le message établissant la session fiable, il contient réellement mon en-tête personnalisé. Cela a un sens car l'inspecteur de message fonctionne très probablement sur des messages distribués alors que le message établissant la session fiable est généré par un code WCF de niveau inférieur.

0

Pour ajouter par programme têtes d'adresse voir MSDN de Address Headers où l'on peut ajouter par programme un en-tête tels que:

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

Cela fonctionne pour moi

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