我正在尝试实现一种端点行为,该行为将自定义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& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& 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
发生什么事了?!?!!
非常感谢任何帮助......
答案 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”