<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>IOCORE &#187; Utveckling</title>
	<atom:link href="http://iocore.se/category/utveckling/feed/" rel="self" type="application/rss+xml" />
	<link>http://iocore.se</link>
	<description>C#, PHP, Shell scripts m.m</description>
	<lastBuildDate>Fri, 14 Oct 2011 23:42:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>ASP.NET MVC &#8211; komprimera html med actionfilter</title>
		<link>http://iocore.se/utveckling/aspnet-mvc-komprimera-html-med-actionfilter/</link>
		<comments>http://iocore.se/utveckling/aspnet-mvc-komprimera-html-med-actionfilter/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 15:56:38 +0000</pubDate>
		<dc:creator>Alexander Nyquist</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Utveckling]]></category>
		<category><![CDATA[asp.net-mvc]]></category>

		<guid isPermaLink="false">http://iocore.se/?p=429</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>Först kommer definitionen av attributet som används för att kunna anropa filtret.</p>
<div class="dean_ch" style="white-space: wrap;">
public class OptimizeHtmlOutputAttribute : ActionFilterAttribute<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">void</span> OnResultExecuting<span class="br0">&#40;</span>ResultExecutingContext filterContext<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HttpResponseBase response = filterContext.<span class="me1">HttpContext</span>.<span class="me1">Response</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.<span class="me1">Filter</span> = new OptimizeHtmlFilter<span class="br0">&#40;</span>response.<span class="me1">Filter</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Filtret består utav lite mer kod, dock är funktionen som utför allt arbete den överlagrade metoden &#8220;Write&#8221;.</p>
<div class="dean_ch" style="white-space: wrap;">
public class OptimizeHtmlFilter : Stream<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; private readonly StringBuilder _responseHtml;<br />
&nbsp; &nbsp; &nbsp; &nbsp; private readonly Stream _responseStream;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public OptimizeHtmlFilter<span class="br0">&#40;</span>Stream inputStream<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseStream = inputStream;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseHtml = new StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co2">#region Filter overrides</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public StringBuilder ResponseHtml<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> _responseHtml; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override bool CanRead<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">true</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override bool CanSeek<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">true</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override bool CanWrite<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">true</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">long</span> Length<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="nu0">0</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">long</span> Position <span class="br0">&#123;</span> get; set; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">void</span> Close<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseStream.<span class="me1">Close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">void</span> Flush<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseStream.<span class="me1">Flush</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">long</span> Seek<span class="br0">&#40;</span><span class="kw4">long</span> offset, SeekOrigin origin<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> _responseStream.<span class="me1">Seek</span><span class="br0">&#40;</span>offset, origin<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">void</span> SetLength<span class="br0">&#40;</span><span class="kw4">long</span> length<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseStream.<span class="me1">SetLength</span><span class="br0">&#40;</span>length<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">int</span> Read<span class="br0">&#40;</span>byte<span class="br0">&#91;</span><span class="br0">&#93;</span> buffer, <span class="kw4">int</span> offset, <span class="kw4">int</span> count<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> _responseStream.<span class="me1">Read</span><span class="br0">&#40;</span>buffer, offset, count<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co2">#endregion</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; public override <span class="kw4">void</span> Write<span class="br0">&#40;</span>byte<span class="br0">&#91;</span><span class="br0">&#93;</span> buffer, <span class="kw4">int</span> offset, <span class="kw4">int</span> count<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">string</span> stringBuffer = Encoding.<span class="kw1">Default</span>.<span class="me1">GetString</span><span class="br0">&#40;</span>buffer<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sb = new StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var lines = stringBuffer.<span class="me1">Split</span><span class="br0">&#40;</span>Environment.<span class="me1">NewLine</span>.<span class="me1">ToCharArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, StringSplitOptions.<span class="me1">RemoveEmptyEntries</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach <span class="br0">&#40;</span>var line in lines<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sb.<span class="me1">Append</span><span class="br0">&#40;</span>line.<span class="me1">Trim</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer = Encoding.<span class="kw1">Default</span>.<span class="me1">GetBytes</span><span class="br0">&#40;</span>sb.<span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _responseStream.<span class="me1">Write</span><span class="br0">&#40;</span>buffer, <span class="nu0">0</span>, buffer.<span class="me1">Length</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Filtret används sedan genom att dekorera Actions (eller för den delen controllers) med [OptimizeHtmlOutput], exempelvis:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="br0">&#91;</span>OptimizeHtmlOutput<span class="br0">&#93;</span><br />
public ActionResult Html<span class="br0">&#40;</span><span class="kw4">int</span> id<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;var report = _repository.<span class="me1">GetReport</span><span class="br0">&#40;</span>id<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> View<span class="br0">&#40;</span><span class="st0">&quot;Csv&quot;</span>, new CsvReport<span class="br0">&#40;</span>report<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://iocore.se/utveckling/aspnet-mvc-komprimera-html-med-actionfilter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

