2013-04-16 38 views
5

我实现了一个IClientMessageInspector以在应用程序中“拦截”传出的Web服务调用。是否可以从BeforeSendRequestAfterReceiveReply内部找出正在调用哪个操作?如何获取IClientMessageInspector中调用的操作名称?

这里有一个类似的问题,How do i get the invoked operation name within a WCF Message Inspector,这是服务器端(接收请求的一方)。我试图做类似的事情,例如

public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     var v = OperationContext.Current.OutgoingMessageProperties["HttpOperationName"]; 
     return null; 
    } 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { 
     var v = OperationContext.Current.OutgoingMessageProperties["HttpOperationName"]; 
    } 

但在传出的请求期间,似乎OperationContext.Current为空,所以我不能使用它。任何想法如何得到它?任何想法如何做到干净(相反,说,解析SOAP XML)?

+0

,因为你是在客户端堆栈如此之低,这是很难的信息你真的需要包装在消息对象中。你有可能使用不同的检查员吗?例如,每个操作都应用IParameterInspector,因此非常简单。它也可以让你避免绑定特定的解决方案,如HTTPOperationName。 – ErnieL

+0

参数检查器将如何工作? –

回答

2

reply.Headers.Actionrequest.Headers.Action怎么样。当然,其余的问题与问题链接相同。因此,完整的代码将是:

var action = reply.Headers.Action.Substring(reply.Headers.Action.LastIndexOf("/", StringComparison.OrdinalIgnoreCase) + 1); 

var action = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf("/", StringComparison.OrdinalIgnoreCase) + 1); 
+4

奇怪..当我测试这个代码'request.Headers.Action'是一个空字符串''“''和'reply.Headers。Action'为null –

+1

很可能是因为在这个阶段,要执行的操作还没有确定http://msdn.microsoft.com/en-us/magazine/cc163302.aspx#S2 – mrd3650

4

从你问效果如何,这可能与IParameterInspector进行评论。操作名称是Before/AfterCall方法的一部分。

只是添加到我的评论中使用的检查员。从Carlos Figueira's blogs

消息督察,在以前的帖子这个系列的描述, 可以让你在邮件是通过WCF 堆栈会完全控制。它们非常强大,但是你必须知道如何处理消息对象 ,这不是 编程最理想的方式。如果WCF中的服务模型通过允许我们根据 强类型操作(即,使用良好的原语和用户定义的 类型)来定义我们的服务来隐藏所有消息框架,则应该有拦截请求/响应的方式 完成所有处理后,从传入的 消息中提取这些参数(或在它们打包到传出消息中之前)。 IParameterInspector就是这样 - 在每次调用之前和之后,检查员有机会检查操作输入,输出 和返回值,与操作 合同中定义的类型相同,不需要转换(唯一的转换需要的是一个演员阵容,因为 参数作为对象传递)。

这是一个完整的命令行程序演示:

using System; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 

namespace WCFClientInspector 
{ 
    public class OperationLogger : IParameterInspector 
    { 
     public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) 
     { 
      Console.WriteLine("Completed operation:" + operationName); 
     } 

     public object BeforeCall(string operationName, object[] inputs) 
     { 
      Console.WriteLine("Calling operation:" + operationName); 
      return null; 
     } 
    } 

    public class OperationLoggerEndpointBehavior : IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
      foreach (ClientOperation operation in clientRuntime.ClientOperations) 
      { 
       operation.ClientParameterInspectors.Add(new OperationLogger()); 
      } 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
     } 
    } 


    [ServiceContract] 
    public interface ISimple 
    { 
     [OperationContract] 
     void DoSomthing(string s); 
    } 

    public class SimpleService : ISimple 
    { 
     public void DoSomthing(string s) 
     { 
      Console.WriteLine("Called:" + s); 
     } 
    } 

    public static class AttributesAndContext 
    { 
     static void Main(string[] args) 
     { 
      ServiceHost simpleHost = new ServiceHost(typeof(SimpleService), new Uri("http://localhost/Simple")); 
      simpleHost.Open(); 

      ChannelFactory<ISimple> factory = new ChannelFactory<ISimple>(simpleHost.Description.Endpoints[0]); 
      factory.Endpoint.EndpointBehaviors.Add(new OperationLoggerEndpointBehavior()); 
      ISimple proxy = factory.CreateChannel(); 

      proxy.DoSomthing("hi"); 

      Console.WriteLine("Press ENTER to close the host."); 
      Console.ReadLine(); 

      ((ICommunicationObject)proxy).Shutdown(); 

      simpleHost.Shutdown(); 
     } 
    } 

    public static class Extensions 
    { 
     static public void Shutdown(this ICommunicationObject obj) 
     { 
      try 
      { 
       obj.Close(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Shutdown exception: {0}", ex.Message); 
       obj.Abort(); 
      } 
     } 
    } 
} 

它应该给输出:

Calling operation:DoSomthing 
    Called:hi 
    Completed operation:DoSomthing 
    Press ENTER to close the host. 
相关问题