Have you ever noticed that when a page is sent in ASP.Net, that it comes in a "pretty printing" sort of format? Ever wanted to get rid of those extra spaces, tabs, etc. to save some bandwidth? It's actually really easy to accomplish. All that you need to do is change the stream that that page uses for output. This can be done by writing your own Stream and changing the response's filter to a new instance of that stream.
The Stream
The stream code is as follows:
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Site
{
public class UglyStream:Stream
{
private string Compression;
private Stream StreamUsing;
/// <summary>
/// Constructor
/// </summary>
/// <param name="StreamUsing">The stream for the page</param>
/// <param name="Compression">The compression we're using (gzip or deflate)</param>
public UglyStream(Stream StreamUsing,string Compression)
{
this.Compression = Compression;
this.StreamUsing = StreamUsing;
}
/// <summary>
/// Doesn't deal with reading
/// </summary>
public override bool CanRead
{
get { return false; }
}
/// <summary>
/// No seeking
/// </summary>
public override bool CanSeek
{
get { return false; }
}
/// <summary>
/// Can write out though
/// </summary>
public override bool CanWrite
{
get { return true; }
}
/// <summary>
/// Nothing to flush
/// </summary>
public override void Flush()
{
}
/// <summary>
/// Don't worry about
/// </summary>
public override long Length
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// No position to take care of
/// </summary>
public override long Position
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// Don't worry about
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <returns></returns>
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
/// <summary>
/// Once again not implemented
/// </summary>
/// <param name="offset"></param>
/// <param name="origin"></param>
/// <returns></returns>
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
/// <summary>
/// Don't worry about
/// </summary>
/// <param name="value"></param>
public override void SetLength(long value)
{
throw new NotImplementedException();
}
/// <summary>
/// Actually writes out the data
/// </summary>
/// <param name="buffer">the page's data in byte form</param>
/// <param name="offset">offset of the data</param>
/// <param name="count">the amount of data</param>
public override void Write(byte[] buffer, int offset, int count)
{
//Copy the data into our own spot
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
//Convert it to a string
string inputstring = Encoding.ASCII.GetString(data);
//Remove pretty print formatting
inputstring = Regex.Replace(inputstring, @">[\s\S]*?<", new MatchEvaluator(Evaluate));
//convert string to bytes again
data = Encoding.ASCII.GetBytes(inputstring);
//compress that data here
//Write it out to the page's stream
StreamUsing.Write(data, 0, inputstring.Length);
}
/// <summary>
/// Evaluates whether the text has spaces, page breaks, etc. and removes them.
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
protected string Evaluate(Match Matcher)
{
string MyString = Matcher.ToString();
MyString = Regex.Replace(MyString, @"\r\n\s*", "");
return MyString;
}
}
}
That's all there is to it. Note though that you have to add in your own compression (or you can look back at my viewstate compression post and cannibalize the code from that). Most of the items aren't even implemented, the only ones that matter are Flush and Write. Both of these have to be implemented. Other than that, who cares. Then all we need to do is on the page we want to use it we add:
Response.Filter=new UglyStream(Response.Filter,"deflate");
And voilà, we have turned off pretty printing. I'm actually a bit surprised that this sort of stuff isn't done by default. The viewstate compression, HTTP compression, pretty printing, etc. or at least give us an easy switch in the config file or something. Maybe it is there and I've just been too lazy to find it, but I'm guessing no... Anyway, use the code, leave feedback, and as always happy coding.
05113efc-45a8-49f0-bc28-3963d47a737f|0|.0