Capturer des requêtes SOAP à un ASP.NET service Web ASMX

tenir compte de la nécessité d'enregistrer les requêtes SOAP entrantes à un ASP.NET service Web ASMX. La tâche consiste à saisir le XML brut envoyé au service web.

Le message entrant doit être enregistré pour déboguer l'inspection. L'application a déjà sa propre bibliothèque de journalisation en cours d'utilisation, donc l'idéal d'utilisation serait quelque chose comme ceci:

//string or XML, it doesn't matter.
string incomingSoapRequest = GetSoapRequest();

Logger.LogMessage(incomingSoapRequest);
  • Existe-t-il des solutions simples pour capturer le XML brut des requêtes SOAP entrantes?
  • quel quels événements traiteriez-vous pour avoir accès à cet objet et aux propriétés pertinentes?
  • y a-t-il un moyen pour L'IIS de capturer la requête entrante et de la pousser vers un log?
28
demandé sur p.campbell 2010-04-12 23:04:09

5 réponses

Un moyen de capturer le message brut est d'utiliser SoapExtensions.

une alternative à SoapExtensions est d'implémenter IHttpModule et de saisir le flux d'entrée au fur et à mesure qu'il arrive.

public class LogModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += this.OnBegin;
    }

    private void OnBegin(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        HttpContext context = app.Context;

        byte[] buffer = new byte[context.Request.InputStream.Length];
        context.Request.InputStream.Read(buffer, 0, buffer.Length);
        context.Request.InputStream.Position = 0;

        string soapMessage = Encoding.ASCII.GetString(buffer);

        // Do something with soapMessage
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}
19
répondu nivlam 2010-04-12 20:03:15

vous pouvez également implémenter en plaçant le code dans Global.asax.cs

protected void Application_BeginRequest(object sender, EventArgs e)
{
    // Create byte array to hold request bytes
    byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];

    // Read entire request inputstream
    HttpContext.Current.Request.InputStream.Read(inputStream, 0, inputStream.Length);

    //Set stream back to beginning
    HttpContext.Current.Request.InputStream.Position = 0;

    //Get  XML request
    string requestString = ASCIIEncoding.ASCII.GetString(inputStream);

}

j'ai une méthode utilitaire dans mon service web que j'utilise pour capturer la requête quand quelque chose se produit que je ne m'attends pas comme une exception non manipulée.

    /// <summary>
    /// Captures raw XML request and writes to FailedSubmission folder.
    /// </summary>
    internal static void CaptureRequest()
    {
        const string procName = "CaptureRequest";

        try
        {
            log.WarnFormat("{0} - Writing XML request to FailedSubmission folder", procName);

            byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];

            //Get current stream position so we can set it back to that after logging
            Int64 currentStreamPosition = HttpContext.Current.Request.InputStream.Position;

            HttpContext.Current.Request.InputStream.Position = 0;

            HttpContext.Current.Request.InputStream.Read(inputStream, 0, HttpContext.Current.Request.ContentLength);

            //Set back stream position to original position
            HttpContext.Current.Request.InputStream.Position = currentStreamPosition;

            string xml = ASCIIEncoding.ASCII.GetString(inputStream);

            string fileName = Guid.NewGuid().ToString() + ".xml";

            log.WarnFormat("{0} - Request being written to filename: {1}", procName, fileName);

            File.WriteAllText(Configuration.FailedSubmissionsFolder + fileName, xml);
        }
        catch
        {
        }

    }

puis sur le web.config je stocke plusieurs valeurs D'application qui définissent le niveau que je veux utiliser pour capturer la requête.

    <!-- true/false - If true will write to an XML file the raw request when any Unhandled exception occurrs -->
    <add key="CaptureRequestOnUnhandledException" value="true"/>

    <!-- true/false - If true will write to an XML file the raw request when any type of error is returned to the client-->
    <add key="CaptureRequestOnAllFailures" value="false"/>

    <!-- true/false - If true will write to an XML file the raw request for every request to the web service -->
    <add key="CaptureAllRequests" value="false"/>

puis dans ma Application_BeginRequest Je l'ai modifié comme ça. Notez que La Configuration est une classe statique que je crée pour lire les propriétés de web.config et d'autres domaines.

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

        if(Configuration.CaptureAllRequests)
        {
            Utility.CaptureRequest();
        }
    }
17
répondu Jim Scott 2011-04-01 21:07:42

Vous savez que vous n'avez pas en fait, besoin de créer un HttpModule droit?

vous pouvez aussi lire le contenu du Request.InputStream à partir de votre asmx WebMethod.

Ici un article que j'ai écrit sur cette approche.

le Code est comme suit:

using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace SoapRequestEcho
{
  [WebService(
  Namespace = "http://soap.request.echo.com/",
  Name = "SoapRequestEcho")]
  public class EchoWebService : WebService
  {

    [WebMethod(Description = "Echo Soap Request")]
    public XmlDocument EchoSoapRequest(int input)
    {
      // Initialize soap request XML
      XmlDocument xmlSoapRequest = new XmlDocument();

      // Get raw request body
      Stream receiveStream = HttpContext.Current.Request.InputStream;

      // Move to beginning of input stream and read
      receiveStream.Position = 0;
      using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
      {
        // Load into XML document
        xmlSoapRequest.Load(readStream);
      }

      // Return
      return xmlSoapRequest;
    }
  }
}
11
répondu Steven de Salas 2013-11-07 18:59:02

Il n'est pas facile à faire. Vous aurez à mettre en œuvre un SoapExtension. L'exemple du lien précédent montre une extension qui peut être utilisée pour enregistrer les données.

si vous utilisez WCF, vous pouvez simplement configurer la configuration pour produire des journaux de messages.


Selon Steven de Salas, vous pouvez utiliser le Request.InputStream propriété dans la méthode Web. Je n'ai pas essayé cela, mais il dit qu'il travaille.

je voudrais tester cela avec http et https, et avec et sans autres extensions SOAP en cours d'exécution en même temps. Ce sont des choses qui pourraient affecter quel genre de flux le InputStream est réglé. Certains flux ne peuvent pas chercher, par exemple, ce qui pourrait vous laisser avec un flux positionné après la fin des données, et que vous ne pouvez pas déplacer au début.

-2
répondu John Saunders 2017-05-23 11:54:18

je sais que j'ai 4 ans de retard... mais maintenant, nous avons un violon pour faire de même.

-2
répondu Amit Ranjan 2015-07-25 06:11:42