2008-12-22 8 views
17

Comment puis-je capturer au mieux le code HTML (dans mon cas, pour la journalisation) rendu par une page aspx?Capture de code HTML généré à partir d'ASP.NET

Je ne veux pas avoir à écrire à la page en utilisant Response.Write, car cela perturbe la mise en page de mon site.

Utilisation du Response.OutputStream ou les résultats de flux de Response.Output dans un ArgumentException ({System.ArgumentException:. Végétalisées était illisible)

+0

En résumé, remplacez la méthode Rendu pour la page. Une question et des réponses similaires [ici] (http://stackoverflow.com/questions/56279/export-aspx-to-html) –

Répondre

23

Bonne question, j'ai dû essayer et voir si je pouvais créer un HttpModule pour faire ce que vous décrivez.

Je n'ai pas eu de chance d'essayer de lire depuis le flux de réponses, mais en utilisant le ResponseFilter m'a donné un moyen de capturer le contenu.

Le code suivant semble très bien fonctionner, et j'ai pensé que vous pourriez peut-être utiliser le code comme base. Mais rappelez-vous ceci est juste quelque chose que j'ai jeté ensemble rapidement, il n'a pas été testé en aucune façon. Donc, ne l'utilisez pas dans n'importe quel environnement de production sans révision/test approprié et autres. N'hésitez pas à commenter;)

public class ResponseLoggerModule : IHttpModule 
{ 
    private class ResponseCaptureStream : Stream 
    { 
     private readonly Stream _streamToCapture; 
     private readonly Encoding _responseEncoding; 

     private string _streamContent; 
     public string StreamContent 
     { 
      get { return _streamContent; } 
      private set 
      { 
       _streamContent = value; 
      } 
     } 

     public ResponseCaptureStream(Stream streamToCapture, Encoding responseEncoding) 
     { 
      _responseEncoding = responseEncoding; 
      _streamToCapture = streamToCapture; 

     } 

     public override bool CanRead 
     { 
      get { return _streamToCapture.CanRead; } 
     } 

     public override bool CanSeek 
     { 
      get { return _streamToCapture.CanSeek; } 
     } 

     public override bool CanWrite 
     { 
      get { return _streamToCapture.CanWrite; } 
     } 

     public override void Flush() 
     { 
      _streamToCapture.Flush(); 
     } 

     public override long Length 
     { 
      get { return _streamToCapture.Length; } 
     } 

     public override long Position 
     { 
      get 
      { 
       return _streamToCapture.Position; 
      } 
      set 
      { 
       _streamToCapture.Position = value; 
      } 
     } 

     public override int Read(byte[] buffer, int offset, int count) 
     { 
      return _streamToCapture.Read(buffer, offset, count); 
     } 

     public override long Seek(long offset, SeekOrigin origin) 
     { 
      return _streamToCapture.Seek(offset, origin); 
     } 

     public override void SetLength(long value) 
     { 
      _streamToCapture.SetLength(value); 
     } 

     public override void Write(byte[] buffer, int offset, int count) 
     { 
      _streamContent += _responseEncoding.GetString(buffer); 
      _streamToCapture.Write(buffer, offset, count); 
     } 

     public override void Close() 
     { 
      _streamToCapture.Close(); 
      base.Close(); 
     } 
    } 

    #region IHttpModule Members 

    private HttpApplication _context; 
    public void Dispose() 
    { 

    } 

    public void Init(HttpApplication context) 
    { 
     _context = context; 

     context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); 
     context.PreSendRequestContent += new EventHandler(context_PreSendRequestContent); 
    } 

    void context_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     _context.Response.Filter = new ResponseCaptureStream(_context.Response.Filter, _context.Response.ContentEncoding); 
    } 

    void context_PreSendRequestContent(object sender, EventArgs e) 
    { 
     ResponseCaptureStream filter = _context.Response.Filter as ResponseCaptureStream; 

     if (filter != null) 
     { 
      string responseText = filter.StreamContent; 

      // Logging logic here 
     } 
    } 

    #endregion 
} 
+0

C'est exactement ce dont j'avais besoin pour http://stackoverflow.com/questions/1020045/how-to-trace-scriptservice-webservice-requests. Merci! – jrummell

+0

J'ai dû utiliser l'événement BeginRequest pour configurer le filtre, PreRequestHandlerExecute ne s'est pas déclenché dans mon HttpModule. Je n'ai pas regardé pourquoi, mais peut-être que cela aidera quelqu'un d'autre. – JeremyWeir

+0

Incroyable solution du problème! –

4

De nombreux testeurs de charge vous permettra de vous connecter les réponses HTTP générées, mais gardez à esprit avec ASP.NET ceux-ci pourraient être de très gros fichiers journaux.

Éditer: Response.Filter selon le code de Tom Jelen est conçu pour donner ce genre de surveillance et Response.Outputstream est autrement illisible.

Edit 2: Pour une page plutôt qu'un HttpModule

public class ObserverStream : Stream 
{ 
    private byte[] buffer = null; 
    private Stream observed = null; 

    public ObserverStream (Stream s) 
    { 
    this.observed = s; 
    } 

    /* important method to extend #1 : capturing the data */ 
    public override void Write(byte[] buffer, int offset, int count) 
    { 
    this.observed.Write(buffer, offset, count); 
    this.buffer = buffer; //captured! 
    } 

    /* important method to extend #2 : doing something with the data */ 
    public override void Close() 
    { 
    //this.buffer available for logging here! 
    this.observed.Close(); 
    } 

    /* override all the other Stream methods/props with this.observed.method() */ 

    //... 

} 

et dans votre Page_Load (ou avant votre réponse écrite de toute façon)

Response.Filter = new ObserverStream(Response.Filter); 
+0

L'utilisation du flux Response.OutputStream ou Response.Output aboutit à une ArgumentException ({System.ArgumentException: Stream n'était pas lisible.) – lastas

+0

Avez-vous cherché à zéro en premier? Écrire dans un MemStream lisible? (juste en train de me brûler VS maintenant parce que je veux savoir comment faire ça) – annakata

+0

Heh, j'étais sur le point de poster tout le code Response.Filter que je venais d'écrire et j'ai trouvé que Tom Jelen avait déjà fait ça. Travaillé pour moi aussi fondamentalement :) – annakata

1

Une façon de faire XMLHTTP côté serveur demande à votre propre serveur. Saisissez le résultat et enregistrez-le dans un fichier ou une base de données.

Vous pouvez également utiliser AJAX sur le client, récupérer le résultat et le POSTER sur le serveur.

+2

doubler sur les demandes semble mauvais étant donné que les données sont là quelque part la première fois – annakata