<?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>eugene.K &#187; http handler</title>
	<atom:link href="http://ekdd.co.il/tag/http-handler/feed/" rel="self" type="application/rss+xml" />
	<link>http://ekdd.co.il</link>
	<description>web developer to web developers</description>
	<lastBuildDate>Tue, 22 Sep 2009 06:05:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>HttpCombiner modifications for better usability</title>
		<link>http://ekdd.co.il/httpcombiner-modifications-for-better-usability/</link>
		<comments>http://ekdd.co.il/httpcombiner-modifications-for-better-usability/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 13:31:25 +0000</pubDate>
		<dc:creator>eugene</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[http handler]]></category>
		<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://ekdd.co.il/?p=113</guid>
		<description><![CDATA[HttpCombiner is a HttpHandler allows you to gather all css and js files together which decreases amount of http requests made to server when user requests a page and also to cache the generated files, which makes you websites to load faster. You can download http handler from Microsoft’s website by clicking here and you [...]]]></description>
			<content:encoded><![CDATA[<p>HttpCombiner is a <a title="http handler explanation" href="http://msdn.microsoft.com/en-us/library/f3ff8w4a%28VS.71%29.aspx" target="_blank">HttpHandler </a>allows you to gather all css and js files together which decreases amount of http requests made to server when user requests a page and also to cache the generated files, which makes you websites to load faster. You can download http handler from Microsoft’s website by <a title="Http Handler" href="http://code.msdn.microsoft.com/HttpCombiner" target="_blank">clicking here</a> and you can read Omar’s article on how to implement the handler <a title="Omar's article on how to use Http handler" href="http://msmvps.com/blogs/omar/archive/2008/08/28/http-handler-to-combine-multiple-files-cache-and-deliver-compressed-output-for-faster-page-load.aspx" target="_blank">here</a>. Original handler written by <a title="Omar Al Zabir's blog" href="http://msmvps.com/blogs/omar/default.aspx" target="_blank">Omar Al Zabir</a>.</p>
<p>It took me few minutes to configure the handler to work, it is easy to use and well documented. So i advice you to read Omar’s post before continuing with modifications.</p>
<p><span id="more-113"></span></p>
<h2><span style="color: #ff0000;"><strong><span style="color: #000000;">What the problem with Omar’s http handler ?</span></strong></span></h2>
<ol>
<li><span style="color: #ff0000;"><span style="color: #000000;">needless number of paremeters which are passed to handler, instead of having 1 parameter ie. css or js , we got 3 parameters. Why to have file type and content type together when js extension clearly means “javascript/text” content type.</span></span></li>
<li>generated by handler output is cached which means old version will be used anytime you access the page which makes imposible to use handler during developement process when we constantly modify JS and CSS files. By default there is a parameter in query string call to handler “v” which stands for version but each change you make on files you will need to update the version number so there won’t be caching.</li>
<li>each JS or CSS file must be defined in web.config which goes against my dynamic thinking</li>
</ol>
<p>if you find these as faults in usability like i do continue reading further …</p>
<h2><strong>How do we fix those issues ?</strong></h2>
<p>First of lets get rid of parameters and just pass one that stands for file type (ie. css or js), second of all lets define folder within the application where all js and css files will be stored so we can loop though folder and dynamically get all files at once without defining each new file and last let’s define global parameter which tells handler whether it is production, development server or just a cache refresh to update website so we won’t directly deal with versioning.</p>
<p>I could rewrite the handler to work as i want it to but Omar did a great job with handler and all credit to him, while i don’t want to create “yet another HttpHandler” to combine css/js files.. My idea was to hack HttpCombiner as fast as i could so i could get to work with it without dealing with it’s design.</p>
<h2><strong>Implementation</strong></h2>
<p><strong><span style="color: #000000;">Step I — web.config</span></strong><strong><br />
</strong></p>
<p>let’s create two folders inside of our assets folder css and js, because handler already loads css you need to move all css files from your App_Theme/ThemeName folder to Assets/Css one and Js files just keep inside Assets/Js.</p>
<p><span style="text-decoration: underline;"> important note, from now on your CSS and JS files are virtually located on the root (where you place the HttpCombiner.ashx) and not inside real Assets/Foldername folder.</span></p>
<p>Once we have two folders and we understood where files gonna reside and where their virtual location will be, let’s tweak web.config file to work with new settings.</p>
<p><em><strong>old code</strong></em></p>
<pre class="brush: xml">
&lt;/appSettings&gt;
&lt;appSettings&gt;
&lt;add key=&quot;Set_Css&quot; value=&quot;~/App_Themes/Default/Css1.css,~/App_Themes/Default/Css2.css&quot;/&gt;
&lt;add key=&quot;Set_Javascript&quot; value=&quot;~/Javascripts/Js1.js,~/Javascripts/Js2.js,http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js&quot;/&gt;
&lt;/appSettings&gt;
</pre>
<p><em><strong>new code</strong></em></p>
<pre class="brush: xml">
&lt;appSettings&gt;
&lt;add key=&quot;css&quot; value=&quot;~/assets/css/&quot;/&gt;
&lt;add key=&quot;js&quot; value=&quot;~/assets/js/&quot;/&gt;
&lt;add key=&quot;refreshCombiner&quot; value=&quot;true&quot;/&gt;
&lt;/appSettings&gt;
</pre>
<p><strong><span style="color: #000000;">Step II — change of urls layout for handler calls</span></strong></p>
<p><strong><span style="color: #000000;">old urls</span></strong></p>
<pre class="brush: html">
&lt;link type=&quot;text/css&quot;  rel=&quot;Stylesheet&quot; href=&quot;HttpCombiner.ashx?s=Set_Css&amp;amp;t=text/css&amp;amp;v=1&quot; /&gt;
&lt;script type=&quot;text/javascript&quot;  src=&quot;HttpCombiner.ashx?s=Set_Javascript&amp;amp;t=type/javascript&amp;amp;v=2&quot; &gt;&lt;/script&gt;
</pre>
<p><strong><span style="color: #000000;">new urls</span></strong></p>
<pre class="brush: html">
&lt;link type=&quot;text/css&quot;  rel=&quot;stylesheet&quot; href=&quot;HttpCombiner.ashx?t=css&quot; /&gt;
&lt;script type=&quot;text/javascript&quot;  src=&quot;HttpCombiner.ashx?t=js&quot; &gt;&lt;/script&gt;
</pre>
<p><strong><span style="color: #000000;">Step III — modification of HttpCombiner.ashx<br />
</span></strong></p>
<p><strong><span style="color: #000000;">old code — lines 22–24<br />
</span></strong></p>
<pre class="brush: c#">

string setName = request[&quot;s&quot;] ?? string.Empty;
string contentType = request[&quot;t&quot;] ?? string.Empty;
string version = request[&quot;v&quot;] ?? string.Empty;
</pre>
<p><strong><span style="color: #000000;">new code<br />
</span></strong></p>
<pre class="brush: c#">

string setName = request[&quot;t&quot;] ?? string.Empty;
string contentType = (setName == &quot;js&quot;) ? &quot;text/javascript&quot; : &quot;text/css&quot;;

string version = &quot;1&quot;;
if (bool.Parse(ConfigurationManager.AppSettings[&quot;refreshCombiner&quot;]))
{
version = new Random().Next(1, 999999).ToString();
}
</pre>
<p><strong><span style="color: #000000;">old code — lines 47–56<br />
</span></strong></p>
<pre class="brush: c#">

string setDefinition =
System.Configuration.ConfigurationManager.AppSettings[setName] ?? &quot;&quot;;
string[] fileNames = setDefinition.Split(new char[] { &#039;,&#039; },
StringSplitOptions.RemoveEmptyEntries);

foreach (string fileName in fileNames)
{
byte[] fileBytes = this.GetFileBytes(context, fileName.Trim(), encoding);
writer.Write(fileBytes, 0, fileBytes.Length);
}
</pre>
<p><strong><span style="color: #000000;">new code<br />
</span></strong></p>
<pre class="brush: c#">

string filesPath = ConfigurationManager.AppSettings[setName];
string[] fileEntries = Directory.GetFiles(HttpContext.Current.Server.MapPath(filesPath));
foreach (string fileName in fileEntries)
{
byte[] fileBytes = this.GetFileBytes(context, filesPath + fileName.Trim().Remove(0, fileName.LastIndexOf(&quot;\\&quot;)), encoding);
writer.Write(fileBytes, 0, fileBytes.Length);
}
</pre>
<p>Hope you enjoyed it !!!</p>
]]></content:encoded>
			<wfw:commentRss>http://ekdd.co.il/httpcombiner-modifications-for-better-usability/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
