从WCF代理的basicHttpBinding获取HTTP请求正文



我正在使用basicHttpBinding通过HTTP调用IIS中托管的WCF服务。为了在服务器上通过验证,必须传递一个自定义标头值,该值是根据HTTP请求本身(标头和正文(如果存在))计算得出的。

我可以使用代理上的客户端消息检查器(System.ServiceModel.Dispatcher.IClientMessageInspector)自定义端点行为(System.ServiceModel.Description.IEndpointBehavior),然后访问消息对象的httpRequest标头,从调用中获取大部分信息。

然而,获取串行化后通过网络发送的消息内容似乎不会立即或明显可用。然而,我可以获得存储在XmlSerializer中的消息本身,这与通过有线发送消息的格式不同。

有没有办法访问这个值?也许是可以注入的另一个检查器或行为,以便在打开或访问通道绑定时调用它?

您必须实现一个自定义IDispatchMessageInspector,并将其注入到IOperationBehaviorIEndpointBehavior属性中。(在ApplyDispatchBehavior()方法中)

IDispatchMessageInspectorAfterReceiveRequest()方法中,您只能通过复制消息体来获得消息体(一旦访问就无效):

private String GetRequestBody(ref Message message)
{
    MessageBuffer buffer = message.CreateBufferedCopy(Int32.MaxValue);
    message = buffer.CreateMessage();
    String xml = null;
    try
    { 
        var copy = buffer.CreateMessage();
        var dicReader = copy.GetReaderAtBodyContents();
        xml = dicReader.ReadOuterXml();
    }
    catch (Exception e)
    {
    }
    return xml;
}

但如果你只想找到一个标头值,你可以简单地用来获取它

private String TryGetHeader(Message request, String headerName)
{
    if (request.Headers.FindHeader(headerName, "HeaderMessageNamespace") != -1)
        return request.Headers.GetHeader<String>(headerName, "HeaderMessageNamespace");
    return null;
}

创建一个像这样的属性,并将其放在WCF服务中要跟踪的方法上:

    public class MyOperationBehaviorAttribute : Attribute, IOperationBehavior
    {
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            if (dispatchOperation.Parent.MessageInspectors.OfType<MyMessageInspector>().Any() == false)
                dispatchOperation.Parent.MessageInspectors.Add(new MyMessageInspector());
        }
        [...]
    }

并实现这样的检查器:

    public class MyMessageInspector : IDispatchMessageInspector
    {
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            var result = TryGetHeader(request, "name");
            return null;
        }
        [...]
    }

客户端的AND:

您必须在服务实例化之后立即注入行为。具有ClientBase类型的MyServiceClient和IEndpointBehavior myBehavior:

((ClientBase<ISomething>)service).Endpoint.Behaviors.Add(myBehavior);

带有

public class MyBehavior : IEndpointBehavior
{
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new MyMessageInspector());
    }
    [...]
}

最新更新