aepheus
aepheus

Reputation: 8187

Response Length in PostRequestHandlerExecute

I want to find out exactly how long the Response sent to the user was, after the fact, for logging purposes. Is there any way to do this from an HttpModule in asp.net (in the PostRequestHandlerExecute event).

Upvotes: 1

Views: 2281

Answers (2)

Martin Vecchione
Martin Vecchione

Reputation: 11

Wish it Help

context.PostRequestHandlerExecute += delegate(object sender, EventArgs e)
{
    HttpContext httpContext = ((HttpApplication)sender).Context;
    HttpResponse response = httpContext.Response;
    // Don't interfere with non-HTML responses
    if (response.ContentType == "text/html")
    {
        response.Filter = new MyRewriterStream(response.Filter);
    }
};

MyRewriterStream Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;

namespace ExecutionTime
{
    public class MyRewriterStream:Stream
    {
        #region "Propiedades"

        private Stream _sink;

        #endregion
        public MyRewriterStream(System.IO.Stream stream)
        {

            _sink = stream;
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
            string outStr;
            outStr = UTF8Encoding.UTF8.GetString(buffer, offset, count);
            strPageSize = strPageSize + outStr;
            StringBuilder sb = new StringBuilder(outStr);

            if (sb.ToString().LastIndexOf("</html>") > 0)
            {
                 string HtmlResponse = "";//HERE PUT YOUR NEW HTML RESPONSE
                 sb.AppendLine(HtmlResponse );
                 byteArray = Encoding.ASCII.GetBytes(sb.ToString());
                 _sink.Write(byteArray, 0, byteArray.Length);
            }
            else
            {
                _sink.Write(buffer, offset, count);
            }

        }

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


        #region Properites

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        //public override void Flush()
        //{
        //    _sink.Flush();
        //}

        public override long Length
        {
            get { return 0; }
        }

        private long _position;
        public override long Position
        {
            get { return _position; }
            set { _position = value; }
        }

        #endregion

        #region Methods

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

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

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

        public override void Close()
        {
            _sink.Close();
        }
        #endregion
    }
}

Upvotes: 1

womp
womp

Reputation: 116987

Unfortunately, HttpResponse.OutputStream is write-only, so this is not very straightforward - any attempts to look at the Length property of the output stream will throw an exception.

The only solution to this I've ever seen is by applying a filter to the Response object, so that the filter can count the bytes.

A quick Google search landed me here, which seems close to the implementation I remember.

Upvotes: 1

Related Questions