Захват HTML, созданного из ASP.NET

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

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

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

Короче говоря, переопределите метод Render для страницы. Аналогичный вопрос и ответы здесь

Peter T. LaComb Jr. 22.12.2008 19:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
1
8 310
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Обновлено: Response.Filter в соответствии с кодом Тома Джелена предназначен для обеспечения такого рода надзора и 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);

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

lastas 22.12.2008 19:05

Вы сначала стремились к нулю? Записать в читаемый MemStream? (сейчас просто зажигаю VS, потому что я хочу знать, как это сделать)

annakata 22.12.2008 19:14

Хех, я как раз собирался опубликовать весь код Response.Filter, который я только что написал, и обнаружил, что Том Джелен уже сделал именно это. У меня тоже в принципе работало :)

annakata 22.12.2008 19:56

Решил, объединив решения annakata и Tom Jelens! Спасибо, парни

lastas 23.12.2008 12:34

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

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

удвоение количества запросов кажется плохим, учитывая, что данные есть где-то в первый раз

annakata 22.12.2008 19:59
Ответ принят как подходящий

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

Мне не повезло с попыткой прочитать из потока ответов, но использование 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
}

Это как раз то, что мне нужно для stackoverflow.com/questions/1020045/…. Спасибо!

jrummell 23.06.2009 23:22

Мне пришлось использовать событие BeginRequest для настройки фильтра, PreRequestHandlerExecute не сработал в моем HttpModule. Я не стал разбираться, почему, но, возможно, это поможет кому-то другому.

JeremyWeir 20.10.2010 03:19

Замечательное решение проблемы!

Antony Blazer 22.12.2010 15:22

Отличное решение. Одно из предложений - использовать StringBuilder для StreamContent, а не строку. В противном случае он выделяет новую память для строки и копирует предыдущую строку каждый раз, когда вызывается "Write", что будет происходить часто, когда .Net строит вашу страницу.

ThisGuy 22.09.2012 22:13

Другие вопросы по теме