2013-04-16 5 views
5

Zaimplementowałem IClientMessageInspector do "przechwytywania" wychodzącego połączenia usługi WWW w mojej aplikacji. Czy można sprawdzić, która operacja jest wywoływana z poziomu BeforeSendRequest i?Jak uzyskać nazwę wywoływanej operacji w obiekcie IClientMessageInspector?

Istnieje podobne pytanie tutaj, How do i get the invoked operation name within a WCF Message Inspector, które jest po stronie serwera (strona odbierająca żądanie). Próbowałem zrobić coś podobnego, np.

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

ale podczas żądania wychodzącego wydaje się, że OperationContext.Current jest zerowy, więc nie mogę używać. Masz pomysł, jak go zdobyć? Każdy pomysł, jak to zrobić w sposób czysty (w przeciwieństwie do, powiedzmy, parsować xml SOAP)?

+0

Jest to trudne, ponieważ jesteś tak nisko w stosie klienta, że ​​informacje naprawdę potrzebujesz jest zawinięty w obiekt wiadomości. Czy masz szansę skorzystać z pomocy innego inspektora? Na przykład stosuje się IParameterInspector na operację i dlatego jest prosty. Pozwoli to również uniknąć wiązania konkretnych rozwiązań, takich jak HTTPOperationName. – ErnieL

+0

jak działałby Inspektor parametrów? –

Odpowiedz

2

Co z reply.Headers.Action i request.Headers.Action. Oczywiście reszta jest tak samo podchwytliwa, jak w połączeniu z pytaniami. Tak pełny kod będzie:

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

lub

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

dziwne .. kiedy testuję ten kod 'request.Headers.Action' jest pustym ciągiem' '" 'i' reply.Headers.Akcja jest null –

+1

najprawdopodobniej dlatego, że na tym etapie operacja do wykonania nadal nie jest jeszcze rozstrzygnięta http://msdn.microsoft.com/en-us/magazine/cc163302.aspx#S2 – mrd3650

4

Z uwag Pytałeś jak robi to można zrobić z IParameterInspector. Nazwa operacji jest częścią metod Before/AfterCall.

Po prostu, aby dodać do moich komentarzy, do którego kontrolera użyć. Od Carlos Figueira's blogs:

inspektorów wiadomości, opisany w poprzednim poście z tej serii, umożliwia pełną kontrolę nad wiadomości przechodzącej przez WCF stosie. Są bardzo potężne, ale musisz wiedzieć, jak radzić sobie z obiektem Message, który nie jest najbardziej pożądanym sposobem programowania . Jeśli model usługi w WCF ukrywa całą strukturę komunikatów, pozwalając nam zdefiniować nasze usługi w kategoriach mocno wpisanych operacji (tj. Przy użyciu ładnych typów pierwotnych i zdefiniowanych przez użytkownika ), powinien istnieć sposób przechwytywania żądań/odpowiedzi po zakończeniu przetwarzania, które wyodrębni te parametry z przychodzących wiadomości (lub zanim zostaną one spakowane w wiadomościach wychodzących). IParameterInspector jest dokładnie tym - przed i po każdym połączeniu, inspektor ma szansę sprawdzić wejścia operacji, wyjścia i zwracać wartość, w tych samych typach, co zdefiniowane w umowie operacyjnej , bez konieczności konwersji (jedyna rzecz potrzebny jest rzut, ponieważ parametry są przekazywane jako obiekty).

Jest to kompletny program komenda linia, która pokazuje:

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

Należy podać dane wyjściowe:

Calling operation:DoSomthing 
    Called:hi 
    Completed operation:DoSomthing 
    Press ENTER to close the host.