开发者

WCF Custom SOAP Header Issues

开发者 https://www.devze.com 2022-12-21 10:50 出处:网络
I\'m trying to implement an endpoint behavior which injects a custom SOAP header into all messages to and from a service.I\'ve gotten pretty close by implementing the approach from the accepted answer

I'm trying to implement an endpoint behavior which injects a custom SOAP header into all messages to and from a service. I've gotten pretty close by implementing the approach from the accepted answer of this question:

WCF WSDL Soap Header on all operations

After implementing that solution, my custom SOAP header does indeed show up in the WSDL; however, when I try to call the methods on my service, I get the following exception/fault:

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

Looking in Reflector at the DataContractSer开发者_运维知识库ializerOperationFormatter.AddHeadersToMessage method thats throwing the exception, leads me to believe that the following snippet is causing the problem...but I'm not sure why.

MessageHeaderDescription description = (MessageHeaderDescription) headerPart.Description;
object parameterValue = parameters[description.Index];

I think the last line above is throwing the exception. The parameters variable is from IDispatchFormatter.SerializeReply

What's going on?!?!!

Any help would be greatly appreciated...


I have used the same example ("WCF WSDL Soap Header on all operations"), and the same error ocurred. To solve this error, I removed the header from the request on income, in function "AfterReceiveRequest" in IDispatchMessageInspector. I have modified the example in such a way, that the header is added only to incoming messages.

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

But much simpliers aproach is to use WCFExtrasPlus: "https://wcfextrasplus.codeplex.com/wikipage?title=SOAP%20Headers&referringTitle=Documentation"


Instead of modifying the contracts using IServiceBehavior, I've found that modifying the exported contract using IContractBehavior and IWsdlExportExtension works fine and no messages need to be rewritten (like in the other listed answer).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号