2013-04-16 4 views
5

Ich habe eine IClientMessageInspector implementiert, um ausgehenden Web Service-Aufruf in meiner Anwendung abzufangen. Ist es möglich, innerhalb der BeforeSendRequest und AfterReceiveReply herauszufinden, welche Operation aufgerufen wird?Wie wird der Name der aufgerufenen Operation in einem IClientMessageInspector abgerufen?

Es gibt eine ähnliche Frage, How do i get the invoked operation name within a WCF Message Inspector, die für die Server-Seite ist (die Seite, die die Anfrage erhält). Ich habe versucht, etwas Ähnliches zu tun, z.B.

aber während der ausgehenden Anfrage scheint OperationContext.Current null, also kann ich dies nicht verwenden. Irgendeine Idee, wie man es bekommt? Irgendeine Idee, wie man es sauber macht (im Gegensatz, um das SOAP xml zu analysieren)?

+0

hart dafür ist, dass Sie so niedrig, in dem Client-Stack sind, dass die Informationen Sie müssen wirklich in das Nachrichtenobjekt eingewickelt werden. Hast du eine Chance, einen anderen Inspektor zu benutzen? Zum Beispiel wird ein IParameterInspector pro Operation angewendet und ist daher geradlinig. Es würde Ihnen auch erlauben, spezifische Lösungen wie HTTPOperationName nicht zu binden. – ErnieL

+0

Wie würde Parameter Inspector arbeiten? –

Antwort

2

Was ist mit reply.Headers.Action und request.Headers.Action. Natürlich ist der Rest genauso knifflig wie in Frage gestellt. So ist der vollständige Code wird sein:

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

oder

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

seltsam .. wenn ich diesen Code testen 'request.Headers.Action' ist eine leere Zeichenfolge' "" und 'reply.Headers.Aktion ist Null –

+1

höchstwahrscheinlich ist es, weil zu diesem Zeitpunkt die auszuführende Operation noch nicht entschieden ist http://msdn.microsoft.com/en-us/magazine/cc163302.aspx#S2 – mrd3650

4

Aus den Kommentaren gefragt, wie Sie tun dies mit IParameterInspector getan werden könnte. Der Operationsname ist Teil der Before/AfterCall-Methode.

Nur zu meinen Kommentaren hinzufügen, welchen Inspektor zu verwenden. Von Carlos Figueira's blogs:

Die Nachrichteninspektoren, in der früheren Post dieser Serie beschrieben, ermöglicht Ihnen die vollständige Kontrolle über die Nachricht über den Stapel WCF gehen. Sie sind sehr mächtig, aber Sie müssen wissen, wie man mit dem Nachrichtenobjekt umgeht, was nicht der wünschenswerteste Weg der Programmierung ist. Wenn das Servicemodell in WCF das gesamte Messaging-Framework ausblendet, indem es uns erlaubt, unsere Services in Form von stark typisierten Operationen zu definieren (dh nice primitive und benutzerdefinierte -Typen), sollte es eine Möglichkeit geben, Anfragen/Antworten abzufangen nach alle die Verarbeitung, um diese Parameter von eingehenden Nachrichten zu extrahieren (oder bevor sie in ausgehenden Nachrichten verpackt sind) ist fertig. Der IParameterInspector ist genau das - vor und nach jedem Anruf, der Inspektor bekommt eine Chance, die Operation Eingänge, Ausgänge und Rückgabewert, in den gleichen Typen wie durch den Vorgang definiert Vertrag, keine Konvertierung benötigt (die einzige Sache benötigt wird ein Cast, da die Parameter als Objekte übergeben werden).

Dies ist ein vollständiges Kommandozeilen-Programm, das zeigt:

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

er den Ausgang geben soll:

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