In ASP.NET, the Response.OutputStream is write-only. As a result, if you attempt to read the length of the response output at any point in stage in the page events, you get the "NotSupportedException". Taking a page from the book of guys who wrote compression filters that compress the response output on-the-fly, I discovered that I could access the length of the response as it is written...
Basically, I wrote a custom class that inherits "Stream" and overrides all of the appropriate stream's methods/properties. The default constructor accepts a Stream object and stores it in a private variable, so the overridden methods/properties all expose the underlying stream's methods/properties. Example: override public bool CanRead { get { return this._stream.CanRead; } }. I declared a "private long _length = 0;" variable and set the value in my stream's "SetLength" method and update it in the "Write" method using the "count" parameter, ensuring the length always reflects the data length. In the "Close" method, I use "base.Close();" and then I can do whatever I want with my private "_length" variable, which contains the length of the response's output stream.
Once I had the class above, I used the following code in the page's "OnLoad" event:
this.Response.Filter = new ObserveResponseLengthStream(this.Response.Filter);
Per Jorge Pereyra's request, here is the code for "write, setLength, flush and seek":
class ObserveResponseLengthStream : Stream
{
private Stream _stream = null;
private long _length = 0;
public ObserveResponseLengthStream(Guid urlKey,
Stream stream)
{
this._stream = stream;
}
public override long Seek(long offset,
SeekOrigin origin)
{
return this._stream.Seek(offset, origin);
}
public override void Flush()
{
this._stream.Flush();
}
public override void SetLength(long value)
{
this._stream.SetLength(value);
this._length = value;
}
public override void Write(byte[] buffer,
int offset,
int count)
{
this._stream.Write(buffer, offset, count);
this._length += (long)count;
}
public override void Close()
{
try
{
this._stream.Close();
}
catch { }
base.Close();
try
{
/*now you know the actual length
of the response in this._length,
so do whatever you want with it*/
}
catch (Exception ex)
{
//make sure your exceptions are handled!
}
}
/*...all the other code simply exposes the
_stream's properties and methods...*/
}