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

时间:2015-02-13 18:44:11

标签: c# wcf basichttpbinding

我使用basicHttpBinding通过HTTP调用IIS中托管的WCF服务。为了在服务器上传递验证,必须传递自定义标头值,从HTTP请求本身(标头和主体,如果存在)计算。

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

但是,获取序列化为通过线路发送的消息内容似乎不会立即或明显可用。然而,我可以将消息本身存储在XmlSerializer中,该消息不会使其以与通过网络发送的格式相同的格式提供。

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

1 个答案:

答案 0 :(得分:3)

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

AfterReceiveRequest()的{​​{1}}方法中,您只能通过复制它来获取邮件正文(一旦访问它就无效):

IDispatchMessageInspector

但是如果你只是想找到一个标题值,你可以简单地得到它:

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

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

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

并实现这样的检查器:

    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());
        }
        [...]
    }

AND为客户端:

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

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

((ClientBase<ISomething>)service).Endpoint.Behaviors.Add(myBehavior);
相关问题