WCF自定义SOAP标头问题

时间:2010-03-02 01:08:21

标签: wcf soap wsdl

我正在尝试实现一种端点行为,该行为将自定义SOAP标头注入到服务的所有消息中。通过从这个问题的接受答案中实施该方法,我已经非常接近了:

WCF WSDL Soap Header on all operations

实现该解决方案后,我的自定义SOAP标头确实显示在WSDL中;但是,当我尝试在我的服务上调用方法时,我得到以下异常/错误:

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

在抛出异常的DataContractSerializerOperationFormatter.AddHeadersToMessage方法中查看Reflector,让我相信下面的代码片段会导致问题......但我不确定原因。

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

我认为上面的最后一行是抛出异常。 parameters变量来自IDispatchFormatter.SerializeReply

发生什么事了?!?!!

非常感谢任何帮助......

1 个答案:

答案 0 :(得分:0)

我使用了相同的示例(“WCF WSDL Soap Header on all operations”),并发生了同样的错误。为了解决这个错误,我在IDispatchMessageInspector中的函数“AfterReceiveRequest”中从收入请求中删除了标题。我已经以这种方式修改了示例,标题只添加到传入消息中。

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

但更简单的方法是使用WCFExtrasPlus:“https://wcfextrasplus.codeplex.com/wikipage?title=SOAP%20Headers&referringTitle=Documentation