web-dev-qa-db-fra.com

Intercepter SOAP messages de et vers un service Web chez le client

J'ai un client qui communique avec un service Web. La classe avec laquelle je communique est une classe C # qui est générée via wsdl.exe. Je veux maintenant enregistrer tous les messages entrants et sortants.

Ce que j'ai fait jusqu'à présent, c'est d'écrire une classe qui hérite de la classe C # générée automatiquement et j'ai remplacé la méthode GetReaderForMessage. De cette façon, je peux accéder au message entrant plus ou moins comme ceci:

protected override XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize)
{
    System.Xml.XmlReader aReader = base.GetReaderForMessage(message, bufferSize);
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.Load(aReader);
    string content = doc.InnerXml.ToString();
    System.Xml.XmlReader aReader2 = System.Xml.XmlReader.Create(new System.IO.StringReader(content));

    return aReader2;
}

Évidemment, je ne suis pas trop satisfait de cette solution, car en gros je crée deux lecteurs xml. Un pour lire le contenu du message SOAP et un pour retourner à l'appelant de la méthode. De plus, je ne peux pas vraiment faire la même chose avec la méthode GetWriterForMessage.

Mais peut-être que je fais juste des choses trop difficiles au départ. Est-il par exemple possible de lire directement le contenu de l'objet SoapClientMessage? J'ai lu quelques articles suggérant que je devrais utiliser SoapExtensions ici, mais d'après ce que je peux comprendre, cela ne fonctionnerait que si le `` client '' que je crée est lui-même un service Web, ce qui n'est pas le cas dans ce cas.

Aucune suggestion?

25
trabart

Je suggérerais de chercher à utiliser une extension SOAP , qui à mon avis est idéale pour ce scénario. Voici quelques liens qui décrivent le processus.

http://msdn.Microsoft.com/en-us/magazine/cc164007.aspx

https://ebay.custhelp.com/cgi-bin/ebay.cfg/php/enduser/std_adp.php?p_faqid=35

http://www.codeproject.com/KB/webservices/efficientsoapextension.aspx

6
Garett

Vous devez utiliser la fonction "Ajouter une référence de service" et non la fonction "Ajouter une référence Web" pour utiliser cette solution, elle peut être utilisée si le service est ASMX ou WCF. (Vous devez utiliser .NET Framework 3.X pour utiliser cette fonctionnalité)

Cet article vous aidera à ajouter la référence de service à votre projet C #.

Pour intercepter et XML de la demande et de la réponse, implémentez ces deux classes:

public class InspectorBehavior : IEndpointBehavior
{
    public string LastRequestXML { 
        get
        {
            return myMessageInspector.LastRequestXML;
        }
    }

    public string LastResponseXML { 
        get
        {
            return myMessageInspector.LastResponseXML;
        }
    }


    private MyMessageInspector myMessageInspector = new MyMessageInspector();
    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {

    }

    public void Validate(ServiceEndpoint endpoint)
    {

    }


    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(myMessageInspector );
    }
}





public class MyMessageInspector : IClientMessageInspector
{
    public string LastRequestXML { get; private set; }
    public string LastResponseXML { get; private set; }
    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
        LastResponseXML = reply.ToString();
    }

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
    {
        LastRequestXML = request.ToString();
        return request;
    }
}

Ensuite, changez le code d'appel en:

MyTestServiceSoapClient client = new MyTestServiceSoapClient();
var requestInterceptor = new InspectorBehavior();
client.Endpoint.Behaviors.Add(requestInterceptor );
client.DoSomething("param1", "param2", "param3");
string requestXML = requestInterceptor.LastRequestXML;
string responseXML = requestInterceptor.LastResponseXML;

**** EDIT **** Ceci n'est pas lié à la technologie côté serveur, vous pouvez l'utiliser avec les services web WCF, ASMX, PHP, ..., j'ai testé sur: http: // www. w3schools.com/webservices/tempconvert.asmx

Et obtenu les XML suivants:

requestXML =

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.Microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/CelsiusToFahrenheit</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <CelsiusToFahrenheit xmlns="http://tempuri.org/">
      <Celsius>50</Celsius>
    </CelsiusToFahrenheit>
  </s:Body>
</s:Envelope>

responseXML =

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
  <soap:Body>
    <CelsiusToFahrenheitResponse xmlns="http://tempuri.org/">
      <CelsiusToFahrenheitResult>122</CelsiusToFahrenheitResult>
    </CelsiusToFahrenheitResponse>
  </soap:Body>
</soap:Envelope>

**** MODIFIER 2 ****

"Ajouter une référence Web" n'est pas spécialisé pour ASMX et n'est pas une technologie côté client ASMX, et "Ajouter une référence de service" n'est pas la technologie côté client WCF, vous pouvez utiliser les deux pour ajouter une référence à ASMX, WCF, développé par JSP ou un service Web développé par PHP, vous avez besoin de votre application pour utiliser .Net Framework 3.5 pour utiliser "Ajouter une référence de service".

Cet article mentionne:

Lorsque vous utilisez la boîte de dialogue Ajouter une référence Web dans Visual Studio, un proxy client est généré à l'aide des informations WSDL et est ajouté au projet Visual Studio. Ceci est généralement utilisé pour les services ASMX, mais vous pouvez également utiliser la boîte de dialogue Ajouter une référence Web pour créer un proxy client pour les services WCF. Cependant, vous devez saisir manuellement l'URL du service et le proxy généré utilise la sérialisation XML, qui est le seul type de sérialisation pris en charge. Pour créer des proxys client pour les services WCF qui prennent en charge le sérialiseur de contrat de données, vous pouvez utiliser l'outil Svcutil.exe ou utiliser la fonctionnalité Ajouter une référence de service des outils de développement Visual Studio pour .NET Framework 3.x.

54
Sawan