Захват HTML, созданный с помощью ASP.NET

Как лучше всего захватить HTML (в моем случае, для ведения журнала), который отображается на aspx-странице?

Я не хочу писать на страницу с помощью Response.Write, так как это испортит мой макет сайта.

Использование потока Response.OutputStream или Response.Output приводит к ArgumentException ({System.ArgumentException: Stream не читается.)

Ответ 1

Хороший вопрос, мне пришлось попробовать и посмотреть, могу ли я создать HttpModule, чтобы делать то, что вы описываете.

Мне не повезло, что вы пытались прочитать из answerestream, но использование ResponseFilter дало мне способ захватить контент.

Следующий код, похоже, работает очень хорошо, и я подумал, что вы можете использовать код в качестве базы. Но помните, что это просто что-то, что я быстро сбросил, он не был протестирован никоим образом. Поэтому не используйте его в любой производственной среде без надлежащего анализа/тестирования и т.д. Не стесняйтесь прокомментировать это, хотя;)

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
}

Ответ 2

Многие тестеры загрузки позволят вам регистрировать генерируемые HTTP-ответы, но имейте в виду, что ASP.NET может быть очень большими лог файлами.

Изменить: Response.Filter в соответствии с кодом Tom Jelen предназначен для обеспечения такого контроля и Response.Outputstream в противном случае нечитаем.

Изменить 2: для страницы, а не для 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() */

  //...

}

и в вашей Page_Load (или до того, как ваш ответ все равно написан)

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

Ответ 3

Один из способов сделать серверный XMLHTTP-запрос на ваш собственный сервер. Возьмите результат и сохраните его в файле или в базе данных.

В качестве альтернативы вы можете использовать AJAX на клиенте, получить результат и отправить его обратно на сервер.