2011-09-21 14 views
2

如何強制IMessageInspector僅在調用特定操作時觸發,而不是在每次調用服務時觸發?目前,我正在將一個自定義的IEndpointBehavior應用到稱爲此IMessageInspector的端點,但這不完全是我想要做的...爲單個操作啓用SOAP消息檢查

回答

3

消息檢查器綁定到調度運行時對象,它是單個爲每個端點,而不是操作。如果參數檢查器有效,那麼您可以使用它(它綁定到操作),但是如果您需要消息檢查器,那麼它不能綁定到單個操作。但是,您可以在檢查器內部檢查操作是否符合您的期望(基於操作標題,每個操作都是唯一的),如下面的代碼所示。

public class StackOverflow_7502134 
{ 
    [ServiceContract] 
    public interface ITest 
    { 
     [OperationContract] 
     string Echo(string text); 
     [OperationContract] 
     int Add(int x, int y); 
    } 
    public class Service : ITest 
    { 
     public string Echo(string text) 
     { 
      return text; 
     } 
     public int Add(int x, int y) 
     { 
      return x + y; 
     } 
    } 
    public class MyInspector : IEndpointBehavior, IDispatchMessageInspector 
    { 
     string[] operationNames; 

     public MyInspector(params string[] operationNames) 
     { 
      this.operationNames = operationNames ?? new string[0]; 
     } 

     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
      endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this); 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
     } 

     public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
     { 
      // by default, action == <serviceContractNamespace>/<serviceContractName>/<operationName> 
      string operationName = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf('/') + 1); 
      if (this.operationNames.Contains(operationName)) 
      { 
       Console.WriteLine("Inspecting request to operation {0}", operationName); 
       Console.WriteLine(request); 
       Console.WriteLine(); 
       return operationName; 
      } 
      else 
      { 
       return null; 
      } 
     } 

     public void BeforeSendReply(ref Message reply, object correlationState) 
     { 
      string operationName = correlationState as string; 
      if (operationName != null) 
      { 
       Console.WriteLine("Inspecting reply from operation {0}", operationName); 
       Console.WriteLine(reply); 
       Console.WriteLine(); 
      } 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     MyInspector inspector = new MyInspector("Add"); // inspecting Add, not Echo 
     host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "").Behaviors.Add(inspector); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
     ITest proxy = factory.CreateChannel(); 

     Console.WriteLine("Calling Echo"); 
     Console.WriteLine(proxy.Echo("Hello world")); 
     Console.WriteLine(); 

     Console.WriteLine("Calling Add"); 
     Console.WriteLine(proxy.Add(4, 5)); 

     ((IClientChannel)proxy).Close(); 
     factory.Close(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
}