2010-03-02 3 views
1

J'essaie d'implémenter un comportement de point de terminaison qui injecte un en-tête SOAP personnalisé dans tous les messages à destination et en provenance d'un service. Je suis devenu assez proche en mettant en œuvre l'approche de la réponse acceptée de cette question:Problèmes d'en-tête SOAP personnalisé WCF

WCF WSDL Soap Header on all operations

Après la mise en œuvre de cette solution, mon en-tête SOAP personnalisé ne montre en effet dans le WSDL; Cependant, lorsque je tente d'appeler les méthodes sur mon service, je reçois l'exception/faute suivante:

<ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
     <HelpLink i:nil="true" /> 
     <InnerException i:nil="true" /> 
     <Message>Index was outside the bounds of the array.</Message> 
     <StackTrace> at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.AddHeadersToMessage(Message message, MessageDescription messageDescription, Object[] parameters, Boolean isRequest) 
    at System.ServiceModel.Dispatcher.OperationFormatter.SerializeReply(MessageVersion messageVersion, Object[] parameters, Object result) 
    at System.ServiceModel.Dispatcher.DispatchOperationRuntime.SerializeOutputs(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc) 
    at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace> 
     <Type>System.IndexOutOfRangeException</Type> 
    </ExceptionDetail> 

regardant dans réflecteur à la méthode DataContractSerializerOperationFormatter.AddHeadersToMessage thats de lancer l'exception, me porte à croire que l'extrait suivant est à l'origine du problème ... mais je ne sais pas pourquoi. Je pense que la dernière ligne ci-dessus lance l'exception. La variable parameters provient de IDispatchFormatter.SerializeReply

Que se passe-t-il?!? !!

Toute aide serait grandement appréciée ...

+0

Quelle est exactement la valeur de description.Index? Est-ce -1? – jrista

+0

Je ne parviens pas à déboguer la méthode DataContractSerializerOperationFormatter.AddHeadersToMessage, mais les objets MessageHeaderDescription que j'injecte ont tous une valeur d'index égale à zéro. Je suppose que cette exception serait levée si 'parameters' était nul ou de longueur nulle, mais je n'ai pas de contrôle sur cette variable (je ne pense pas) – WayneC

Répondre

0

J'ai utilisé le même exemple (« WCF WSDL Soap Header on all operations »), et la même erreur se est produite. Pour résoudre cette erreur, j'ai supprimé l'en-tête de la requête sur le revenu, dans la fonction "AfterReceiveRequest" dans IDispatchMessageInspector. J'ai modifié l'exemple de telle sorte que l'en-tête est ajouté uniquement aux messages entrants.

[DataContract(Name = "AuthHeader", Namespace = "web")] 
public class AuthHeader 
{ 
    [DataMember(Order = 1)] 
    public string UserName { get; set; } 
    [DataMember(Order = 2)] 
    public string Password { get; set; } 
} 

public class SoapHeaderEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior 
{ 
    #region BehaviorExtensionElement Members 

    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(SoapHeaderEndpointBehavior); 
     } 
    } 

    protected override object CreateBehavior() 
    { 
     return new SoapHeaderEndpointBehavior(); 
    } 
    #endregion 

    #region IEndpointBehavior Members 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
     //throw new NotImplementedException(); 
    } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     var inspector = new FvsMessageInspector(); 
     clientRuntime.MessageInspectors.Add(inspector); 
    } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { 
     var channelDispatcher = endpointDispatcher.ChannelDispatcher; 
     if (channelDispatcher == null) 
      return; 
     foreach (var ed in channelDispatcher.Endpoints) 
     { 
      var inspector = new FvsMessageInspector(); 
      ed.DispatchRuntime.MessageInspectors.Add(inspector); 
     } 

     foreach (OperationDescription operationDescription in endpoint.Contract.Operations) 
     { 
      string nmm = operationDescription.Name; 
      foreach (MessageDescription msgDescription in operationDescription.Messages) 
      { 
       if (msgDescription.Direction == MessageDirection.Input) 
       { 
        MessageHeaderDescription header = new MessageHeaderDescription("AuthHeader", "web"); 
        header.Type = typeof(AuthHeader); 
        msgDescription.Headers.Add(header); 
       } 
      } 
     } 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
     //throw new NotImplementedException(); 
    } 

    #endregion 
} 

public class FvsMessageInspector : IDispatchMessageInspector, IClientMessageInspector 
{ 
    #region IDispatchMessageInspector 

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     int i = request.Headers.FindHeader("AuthHeader", "web"); 
     if (i >= 0) 
     { 
      AuthHeader header = request.Headers.GetHeader<AuthHeader>(i); 
      //Use header info here 
      request.Headers.RemoveAt(i); 
     } 
     return null; 
    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     //No need to do anything else 
    } 

    #endregion 

    #region IClientMessageInspector 

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     return null; 
    } 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { 
     //No need to do anything else 
    } 

    #endregion 
} 

Mais beaucoup simpliers aproche est d'utiliser WCFExtrasPlus: "https://wcfextrasplus.codeplex.com/wikipage?title=SOAP%20Headers&referringTitle=Documentation"

Questions connexes