Feb 18, 2010ASP.NET MVC – komprimera html med actionfilter
Genom att komprimera sin html kan man spara åtskillig datamängd. Jag tänkte här dela med mig av ett Actionfilter till ASP.NET MVC för att komprimera all output (genom att strippa bort onödig whitespace). Med nedanstående filter sparade jag 46kb per sidvisning, vilket blir relativt mycket om man har en välbesökt sida.
Först kommer definitionen av attributet som används för att kunna anropa filtret.
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
HttpResponseBase response = filterContext.HttpContext.Response;
response.Filter = new OptimizeHtmlFilter(response.Filter);
}
}
Filtret bestÃ¥r utav lite mer kod, dock är funktionen som utför allt arbete den överlagrade metoden “Write”.
{
private readonly StringBuilder _responseHtml;
private readonly Stream _responseStream;
public OptimizeHtmlFilter(Stream inputStream)
{
_responseStream = inputStream;
_responseHtml = new StringBuilder();
}
#region Filter overrides
public StringBuilder ResponseHtml
{
get { return _responseHtml; }
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return 0; }
}
public override long Position { get; set; }
public override void Close()
{
_responseStream.Close();
}
public override void Flush()
{
_responseStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return _responseStream.Seek(offset, origin);
}
public override void SetLength(long length)
{
_responseStream.SetLength(length);
}
public override int Read(byte[] buffer, int offset, int count)
{
return _responseStream.Read(buffer, offset, count);
}
#endregion
public override void Write(byte[] buffer, int offset, int count)
{
string stringBuffer = Encoding.Default.GetString(buffer);
var sb = new StringBuilder();
var lines = stringBuffer.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
sb.Append(line.Trim());
buffer = Encoding.Default.GetBytes(sb.ToString());
_responseStream.Write(buffer, 0, buffer.Length);
}
}
Filtret används sedan genom att dekorera Actions (eller för den delen controllers) med [OptimizeHtmlOutput], exempelvis:
public ActionResult Html(int id)
{
var report = _repository.GetReport(id);
return View("Csv", new CsvReport(report));
}
Dock bör man komma ihåg att inte optimera där det inte behövs. Man bör alltid profilera koden för att se vart flaskhalsarna sitter.
