2008-12-22 9 views
17

¿Cómo puedo capturar mejor el HTML (en mi instancia, para el registro) representado por una página aspx?Captura de HTML generado desde ASP.NET

No quiero tener que volver a escribir en la página utilizando Response.Write, ya que estropea el diseño de mi sitio.

Utilizando el Response.OutputStream o los resultados de flujo de Response.Output en un ArgumentException ({System.ArgumentException:. Stream no era legible)

+0

En pocas palabras, anule el método Render para la página. Preguntas y respuestas similares [aquí] (http://stackoverflow.com/questions/56279/export-aspx-to-html) –

Respuesta

23

Buena pregunta, tuve que probar y ver si podía crear un HttpModule para hacer lo que está describiendo.

No tuve suerte tratando de leer de la corriente de respuesta, pero el uso de ResponseFilter me dio una forma de capturar el contenido.

El siguiente código parece funcionar bastante bien, y pensé que tal vez podría usar el código como base. Pero recuerda que esto es algo que lancé rápidamente, no ha sido probado de ninguna manera. Así que no lo use en ningún entorno de producción sin una revisión/prueba adecuada y tal. Sin embargo, no dude en comentar al respecto;)

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

Eso es justo lo que necesitaba para http://stackoverflow.com/questions/1020045/how-to-trace-scriptservice-webservice-requests. ¡Gracias! – jrummell

+0

Tuve que usar el evento BeginRequest para configurar el filtro, PreRequestHandlerExecute no se disparó en mi HttpModule. No me fijé en por qué, pero tal vez eso ayudará a alguien más. – JeremyWeir

+0

¡Solución asombrosa del problema! –

4

Muchos probadores de carga le permitirá iniciar la sesión las respuestas HTTP generadas, pero hay que tener en mente con ASP.NET esos podrían ser algunos archivos de registro muy grandes.

Editar: Response.Filter según el código de Tom Jelen está diseñado para proporcionar este tipo de supervisión y Response.Outputstream no se puede leer.

Edición 2: Para una página en lugar de 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() */ 

    //... 

} 

y en su Load (o antes de que su respuesta está escrita de todos modos)

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

El uso de los resultados de Response.OutputStream o Response.Output en una ArgumentException ({System.ArgumentException: Stream no fue legible.) – lastas

+0

¿Pretendiste poner a cero primero? Escribir en un MemStream legible (acaba de encender VS ahora porque quiero saber cómo hacerlo) – annakata

+0

Heh, estaba a punto de publicar todo el código Response.Filter que acababa de escribir y encontré que Tom Jelen ya había hecho exactamente eso. También funcionó básicamente para mí :) – annakata

1

Una forma de hacer Xmlhttp del lado del servidor solicite su propio servidor. Toma el resultado y guárdalo en un archivo o DB.

Alternativamente, puede utilizar AJAX en el cliente, tomar el resultado y POST volver al servidor.

+2

duplicar las solicitudes parece malo dado que los datos están ahí en alguna parte la primera vez – annakata

Cuestiones relacionadas