<?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>PHP vs .Net &#187; MVC</title>
	<atom:link href="http://www.phpvs.net/category/mvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.phpvs.net</link>
	<description>ASP.Net and PHP go head to head</description>
	<lastBuildDate>Sat, 24 Dec 2011 18:20:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ASP.Net MVC &#8211; How to route to images or other file types</title>
		<link>http://www.phpvs.net/2009/08/06/aspnet-mvc-how-to-route-to-images-or-other-file-types/</link>
		<comments>http://www.phpvs.net/2009/08/06/aspnet-mvc-how-to-route-to-images-or-other-file-types/#comments</comments>
		<pubDate>Fri, 07 Aug 2009 04:23:51 +0000</pubDate>
		<dc:creator>morgan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[ASP.Net]]></category>
		<category><![CDATA[ASP.Net MVC]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.phpvs.net/?p=123</guid>
		<description><![CDATA[A recent question on Stack Overflow (and subsequent answer that I wrote for it) inspired this post. I had recently been discussing URL rewriting in depth with my brother, and have also been doing some introductory work with the routing engine in ASP.Net MVC, and the question piqued my interest since I had been meaning [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.phpvs.net/wp-content/uploads/2009/08/Image.png"><img class="alignright size-full wp-image-228" style="border: 0pt none;" title="Image" src="http://www.phpvs.net/wp-content/uploads/2009/08/Image.png" alt="" width="256" height="256" /></a>A <a href="http://stackoverflow.com/questions/1146652/how-do-i-route-images-using-asp-net-mvc-routing">recent question on Stack Overflow</a> (and subsequent answer that I wrote for it) inspired this post.  I had recently been discussing URL rewriting in depth with my brother, and have also been doing some introductory work with the routing engine in ASP.Net MVC, and the question piqued my interest since I had been meaning to look at this more closely for some time.</p>
<p>The question on Stack Overflow is titled &#034;How do I route images with ASP.Net MVC&#034;, but fundamentally the question is really asking &#034;<strong>how can I use ASP.Net MVC to re-route URL&#039;s to actual physical files, rather than methods of a controller?</strong>&#034;</p>
<p>To be clear, lets address the conceptual differences between routing and url rewriting.  Url rewriting takes the requested URL and modifies it before your code ever sees it.  As far as your application is concerned, the client requested the rewritten URL.  All that URL rewriting does is to change one URL into another URL, based on pattern matching.</p>
<p>Routing is a different and much more powerful beast.  The ASP.Net routing engine maps an URL to a &#034;resource&#034;, based on a set of routes.  The first route to match the requested URL wins the prize, and sends the request off to the resource it chooses.  For the ASP.Net MVC framework (which uses <code>System.Web.Routing</code> under the hood), a resource is something that can handle the request object, which is always a piece of code.</p>
<p>So where does that leave physical files?  If a request is always parsed by the routing engine and then handed off to some function somewhere, how can we ever route a request for an image to actually return the physical image?</p>
<p>Well, it takes a tiny bit of legwork, but once we&#039;re through it, I&#039;m confident you will see the huge advantages that routing has over simple url-rewriting.  We will show the equivalent of url-rewriting by handling a request for an image using an URL that doesn&#039;t map to a physical path, but be able to return the image anyway.</p>
<h2>Handling the Request</h2>
<p>First off, we need to handle the request that we want to re-route to a physical file.  Out of the box, ASP.Net MVC uses an instance of the <code>MvcRouteHandler </code>object to handle every request.  <code>MvcRouteHandler </code> hides all the complexities of taking the requested URL, breaking it down into parts, finding the right controller in your application, instantiating it and passing it all the data it needs.</p>
<p>The end result of <code>MvcRouteHandler </code>is not what we desire. We want to return an image, not instantiate a controller and run a method.   We want to skip dealing with controllers altogether in this case.  So lets create our own route handler that we&#039;ll use instead.</p>
<p>To do so, we simply implement <code>IRouteHandler</code>, an interface exposed by ASP.Net MVC that actually inherits from <code>IHttpHandler</code>.  This means that what we&#039;re writing is the ASP.Net MVC equivalent of an .ashx file for a webforms app -- we&#039;re inserting our own handling module into the ASP.Net pipeline, that will handle the request much closer to the webserver/http level, rather than at the ASP.Net application level.</p>
<p><code>IRouteHandler </code>only has one method that we need to implement, which is <code>GetHttpHandler()</code>.</p>
<pre class="prettyprint"><code><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">Generic</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="typ">Compilation</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="typ">Routing</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="pln">UI</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> MvcApplication1
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ImageRouteHandler</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IRouteHandler</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">IHttpHandler</span><span class="pln"> </span><span class="typ">GetHttpHandler</span><span class="pun">(</span><span class="typ">RequestContext</span><span class="pln"> requestContext</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">string</span><span class="pln"> filename </span><span class="pun">=</span><span class="pln"> requestContext</span><span class="pun">.</span><span class="typ">RouteData</span><span class="pun">.</span><span class="typ">Values</span><span class="pun">[</span><span class="str">"filename"</span><span class="pun">]</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">;</span><span class="pln">

            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="com">requestContext.HttpContext.Response.Clear();
                requestContext.HttpContext.Response.StatusCode = 404;
                requestContext.HttpContext.Response.End();
</span><span class="pln">            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">Clear</span><span class="pun">();</span><span class="pln">
                requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetContentType</span><span class="pun">(</span><span class="pln">requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Request</span><span class="pun">.</span><span class="typ">Url</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">

                </span><span class="com">// find physical path to image here.  </span><span class="pln">
                </span><span class="kwd">string</span><span class="pln"> filepath </span><span class="pun">=</span><span class="pln"> requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Server</span><span class="pun">.</span><span class="typ">MapPath</span><span class="pun">(</span><span class="str">"~/test.jpg"</span><span class="pun">);</span><span class="pln">

                requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">WriteFile</span><span class="pun">(</span><span class="pln">filepath</span><span class="pun">);</span><span class="pln">
                requestContext</span><span class="pun">.</span><span class="typ">HttpContext</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">End</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="typ">GetContentType</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> path</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Path</span><span class="pun">.</span><span class="typ">GetExtension</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">case</span><span class="pln"> </span><span class="str">".bmp"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Image/bmp"</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">case</span><span class="pln"> </span><span class="str">".gif"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Image/gif"</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">case</span><span class="pln"> </span><span class="str">".jpg"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Image/jpeg"</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">case</span><span class="pln"> </span><span class="str">".png"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Image/png"</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">default</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span></code></pre>
<p>The above <code>IRouteHandler </code>is pretty simple.  Ignoring the <code>GetContentType </code>helper method, there&#039;s really only two things happening.  First, we check for a &#034;filename&#034; parameter that got passed in to our handler (more on that in a second).  If it&#039;s not there, we return a 404 response.  Otherwise, we attempt to open up the physical file &#034;test.jpg&#034;, and stream it to the browser.</p>
<p>Clearly, this should be adapted to your needs by actually using the filename parameter to find the physical files on your system.   But moving on -- how do we invoke this from our MVC app?  And how do we pass in the filename parameter, of which we&#039;d like to reroute to some other physical path?</p>
<h2>Routing the Request to the Custom Handler</h2>
<p>Well, this is the easy part.  Where you&#039;d normally define your routes in <code>Global.asax</code>, simply use <code>routes.Add()</code>, instead of <code>routes.MapRoute()</code>.  Just like this:</p>
<pre>routes.Add("ImagesRoute",
                 new Route("graphics/{filename}", new ImageRouteHandler()));</pre>
<p>This method of adding our route allows us to specify our custom <code>IRouteHandler</code>, rather than <code>routes.MapRoute()</code>, which by default uses an instance of <code>MvcRouteHandler</code>.  So now, we&#039;ve defined a route that matches against any requested URL containing &#034;graphics/&#034;, and puts the rest of the URL into the &#034;filename&#034; bucket of the <code>RouteDataDictionary</code>, and hands it off to our <code>IRouteHandler</code>.  This is how we pass the filename parameter into our custom route handler -- basically the same way we pass things into controllers, by defining the variables in the route pattern.</p>
<p>We&#039;ve successfully routed all URL&#039;s containing &#034;graphics/&#034;, which doesn&#039;t physically exist in our web application, and returning &#034;temp.jpg&#034;, which could exist anywhere.  With a bit of coding around the file IO, you could return files from anywhere.</p>
<p>And that&#039;s pretty much it!  You might be thinking, &#034;this seems like a lot of extra work just to re-route a URL to a physical file that already existed in my web app!&#034;.   If you take a step back though, you&#039;ll see the power of this approach.  What if you wanted to log every request to the original URL to a special log file?  What if you wanted to also transform the image before returning it?  Perhaps launch a system executable or asynchronously hit a web service?  What if you wanted to&#8230;?</p>
<p>In a nutshell, by inserting your own HttpHandlers into the ASP.Net pipeline to handle routed requests, you can code <em>anything that you&#039;d like to happen</em> when a request comes in, rather than just rewriting it to some other URL.</p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.phpvs.net%2f2009%2f08%2f06%2faspnet-mvc-how-to-route-to-images-or-other-file-types%2f"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.phpvs.net%2f2009%2f08%2f06%2faspnet-mvc-how-to-route-to-images-or-other-file-types%2f&amp;bgcolor=FF9933&amp;cbgcolor=D4E1FD" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpvs.net/2009/08/06/aspnet-mvc-how-to-route-to-images-or-other-file-types/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>ASP.Net Web Forms dying a slow death?</title>
		<link>http://www.phpvs.net/2008/04/25/aspnet-web-forms-dying-a-slow-death/</link>
		<comments>http://www.phpvs.net/2008/04/25/aspnet-web-forms-dying-a-slow-death/#comments</comments>
		<pubDate>Sat, 26 Apr 2008 02:02:11 +0000</pubDate>
		<dc:creator>morgan</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[ASP.Net]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://www.phpvs.net/2008/04/25/aspnet-web-forms-dying-a-slow-death/</guid>
		<description><![CDATA[Being a web programmer for the last 10 years, I&#039;ve seen a few different paradigms come and go in the web world. Looking around today, I can&#039;t help but think that the writings are on the wall for the ASP.Net &#034;webforms&#034; web application model. When it debuted, it was revolutionary to have a fully typed, [...]]]></description>
			<content:encoded><![CDATA[<p>Being a web programmer for the last 10 years, I&#039;ve seen a few different paradigms come and go in the web world.  Looking around today, I can&#039;t help but think that the writings are on the wall for the ASP.Net &#034;webforms&#034; web application model.  When it debuted, it was revolutionary to have a fully typed, compiled OO framework that was virtually portable to mobile and desktop.  However, since then, ASP.Net has not done much to improve the initial offerings.  Yes, the 2.0 framework was much more robust, and VS 2005 had lots of IDE help for webmasters, but fundamentally, the same problems that held developers of 1.0 sites back are holding developers of 3.0 sites back -- namely, the ASP.Net page lifecycle.</p>
<p>Viewstate and lifecycle events are still very confusing for new ASP.Net programmers.  There is no easy way for them to immediately &#034;get it&#034; -- they have to spend the time in the trenches, watching their data disappear on post back, or double-bind, and flail around with building and rendering their own web controls.  They have to see the DataGrid spew its html diarrhea and spend hours customizing it.  They have to have that client ask them &#034;what the hell is all this javascript, and why are the pages so big?&#034; and figure out just what the heck all that gibberish on their pages are.</p>
<p>Moving up the experience chain, Viewstate and lifecycle events represent a significant amount of design and front-end time on a web application even for those that have been doing it for a while.  You have to balance your state management with your html optimization, caching, and application maintainability.  Often you have to build your own state-tracking structures or extend existing ones.  You have to carefully consider whether to roll your own custom controls or buy third party interfaces and rely on their javascript and state programming (or maybe their support team!)  And for very simple &#034;read-only&#034; web sites, viewstate just gets in the way.</p>
<p>So in summary, Viewstate and lifecycle are still be a pain in the butt, and still represent hurdles for new programmers.  Years ago, it was worth the annoyances and problems, because you could write strongly typed, object oriented portable code without getting lost in folders and folders of scripted sites.  So why might it be dying?  Well&#8230;</p>
<p>The first item on the agenda is <a href="http://silverlight.net/">Silverlight</a>.  ASP.Net represented significant advantages for writing portable code that was closer to classic desktop programming, as it abstracted out much of the xhtml.  But now I&#039;ve seen web application developers swoon over Silverlight.  If their reaction is any indication, and the amount of momentum that Microsoft is putting into WPF, many shops are going to give up programming their internal or non-public projects in ASP.Net and move to Silverlight instead.   I&#039;m personally still skeptical about Silverlight&#039;s market penetration, as there are many gaps it doesn&#039;t fill for content publishers.  But it&#039;s not a minor consideration.</p>
<p>Second is the new ASP.Net MVC framework.  MVC is an old model that&#039;s rapidly gaining traction in the web world, and with the introduction of the ASP.Net MVC framework, it is hard to see any clear advantage to the older webforms model.  From <a href="http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx">Scott Guthrie&#039;s Introductory MVC post</a> a couple months ago:</p>
<blockquote><p>To help enforce testability, the MVC framework today does not support postback events directly to server controls within your Views.  Instead, ASP.NET MVC applications generate hyperlink and AJAX callbacks to Controller actions -- and then use Views (and any server controls within them) solely to render output.  This helps ensure that your View logic stays minimal and solely focused on rendering, and that you can easily unit test your Controller classes and verify all Application and Data Logic behavior independent of your Views. </p></blockquote>
<p>And finally, we come to REST, another model that is gaining traction.  True REST and webforms are mutually exclusive since REST involves heavy reliance on mapping resource locators to known states of an application.  This model has lots of advantages for web services and data-based applications, especially in the realms of testing, while ASP.Net Webform applications are often built around one URL for many states, using Viewstate and Session as your state map, which are of course lost between sessions and server restarts.  </p>
<p>So long story short&#8230; I think we&#039;re seeing the beginning of a new paradigm.  In 5 years, will anyone still be developing with true ASP.Net Webforms?  It will be interesting to see!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phpvs.net/2008/04/25/aspnet-web-forms-dying-a-slow-death/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

