我正在使用basicHttpBinding
通过HTTP调用IIS中托管的WCF服务。为了在服务器上通过验证,必须传递一个自定义标头值,该值是根据HTTP请求本身(标头和正文(如果存在))计算得出的。
我可以使用代理上的客户端消息检查器(System.ServiceModel.Dispatcher.IClientMessageInspector
)自定义端点行为(System.ServiceModel.Description.IEndpointBehavior
),然后访问消息对象的httpRequest
标头,从调用中获取大部分信息。
然而,获取串行化后通过网络发送的消息内容似乎不会立即或明显可用。然而,我可以获得存储在XmlSerializer中的消息本身,这与通过有线发送消息的格式不同。
有没有办法访问这个值?也许是可以注入的另一个检查器或行为,以便在打开或访问通道绑定时调用它?
您必须实现一个自定义IDispatchMessageInspector
,并将其注入到IOperationBehavior
或IEndpointBehavior
属性中。(在ApplyDispatchBehavior()
方法中)
在IDispatchMessageInspector
的AfterReceiveRequest()
方法中,您只能通过复制消息体来获得消息体(一旦访问就无效):
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());
}
[...]
}