<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Pedro Reys</title>
	
	<link>http://pedroreys.com</link>
	<description>Sou Tricolor de Coração</description>
	<lastBuildDate>Wed, 04 Apr 2012 20:13:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/pedroreys" /><feedburner:info uri="pedroreys" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>WebApiContrib</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/Bm9PcxWGLfo/</link>
		<comments>http://pedroreys.com/2012/04/04/webapicontrib/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 18:35:29 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[WebAPIContrib]]></category>

		<guid isPermaLink="false">http://pedroreys.com/?p=122</guid>
		<description><![CDATA[The  announcement of the ASP.NET Web API got a lot of people interested in playing with, bending, learning the framework to see what was possible to do with it. Some folks were doing that already back when it was WCFWebApi. &#8230;<p class="read-more"><a href="http://pedroreys.com/2012/04/04/webapicontrib/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>The  announcement of the ASP.NET Web API got a lot of people interested in playing with, bending, learning the framework to see what was possible to do with it. Some folks were doing that already back when it was WCFWebApi. But the move to the ASP.NET team and having it being part of the ASP.NET MVC 4 beta definitely brought a lot of attention to the Web Api framework.</p>
<h3>The WebApiContrib organization</h3>
<p>With all that attention, and people playing with it, different contrib efforts were sparkling all around. There was the original <a href="http://webapicontrib.codeplex.com/">WcfWebApiContrib</a> maintained by <a href="http://www.bizcoder.com/">Darrel Miller</a>. We at <a href="http://www.headspring.com/">Headspring</a> created our own contrib. Folks from <a href="http://www.thinktecture.com/">Thinktecture</a> created there own. Some other authors were pushing their own extensions to their own repositories. Basically, it was a mess.</p>
<p><a href="http://wizardsofsmart.net/">Ryan Riley</a> then started the effort to bring everybody together to contribute to a single contrib project. He created <a href="https://github.com/WebApiContrib">an organization</a> on github and <a href="https://groups.google.com/forum/#!forum/webapicontrib">a mailing list</a>. After I got contacted by Ryan, I talked with the other Headspring folks and we decided to transfer our <a href="https://github.com/WebApiContrib/WebAPIContrib">WebApiContrib</a> repository from our <a href="https://github.com/HeadspringLabs">HeadspringLabs</a> organization to the WebApiContrib one.</p>
<p>This was the first move that we made, after that, Thinktecture extensions were moved and the handlers from the WcfWebApiContrib were also moved.</p>
<h3>How can I get it?</h3>
<p>Right now, you can <a href="https://github.com/WebApiContrib/WebAPIContrib">head to the github repository</a> and pull the code. I know it’s kinda ghetto in these <a href="http://nuget.org/">Nuget</a> and <del>Open Rasta</del> <a href="http://www.openwrap.org/">OpenWrap</a> days.</p>
<p>In order to fix this, and <a href="http://chrismissal.lostechies.com">Chris Missal</a> is working on it, we need to solve some few issues:</p>
<ul>
<li>Add the packaging task to our build – not a big deal</li>
<li>Have a CI server to generate the packages for us – Chris talked with the Codebetter folks and we will have it done by the end of the week approximately</li>
<li>Agree on how we are going organize the packages and distribute it.</li>
</ul>
<p>The latter issue has two parts: package organization and distribution</p>
<p><span style="text-decoration: underline;">Package Organization:</span> We are structuring the code so that one can install the core package that has no dependencies. This will give you all extensions that have no extra dependencies. For extensions that depends on other packages we are going to create a specific packages.</p>
<p>For example, if you want to use the <a href="https://github.com/WebApiContrib/WebAPIContrib/blob/master/src/WebApiContrib/MessageHandlers/NotAcceptableMessageHandler.cs">NotAcceptableMessageHandler</a>, that has no dependencies, all you have to do is install the core package. On the other hand, if you want to use the <a href="https://github.com/WebApiContrib/WebAPIContrib/blob/master/src/WebApiContrib.Formatting.ServiceStack/ServiceStackTextFormatter.cs">ServiceStackTextFormatter</a>, a Media Type Formatter that uses ServiceStack.Text to handle JSON serialization, you will have to install the WebApiContrib.Formatting.ServiceStackTextFormatter package. Our goal is to keep contrib’s users packages dependencies clean, and only have what is really necessary for what the user is trying to do.</p>
<p><span style="text-decoration: underline;">Distribution:</span> Nuget currently has two <a href="http://nuget.org/packages?q=WebApiContrib">WebApiContrib packages</a>. Those were created for the WCFWeb APIContrib project. This means that replacing those packages will break everything for people that was relying on the WCF version of the package. This might be ok to do, as the WCFWebApi no longer exist and we are going to deprecate the WCFContrib as well. But we haven’t decided that yet. And I’m willing to get some ideas on what should we do to make this as frictionless as possible.</p>
<p>I expect all this to be fixed by next week.</p>
<h3>What’s next</h3>
<p>We don’t have an official roadmap besides<a href="https://github.com/WebApiContrib/WebAPIContrib/issues?sort=created&amp;direction=desc&amp;state=open"> the issues list on github</a>. Besides what’s there, I have some ideas that are now floating on my head but I haven’t started working on them yet:</p>
<p><span style="text-decoration: underline;">Provide a better way of creating/embedding links on resources</span>. The ASP.NET Web API has no built in helper to embed links into resources. My goal is to have a helper to make it easier, and hopefully in a strongly typed way, to configure your resource so that the Media Type Formatter can then pull that information and include the links in the resource representation.</p>
<p><span style="text-decoration: underline;">Api Documentation Generation</span>. It’s key for the success of a api that it’s well documented. It’s in the <a href="http://aspnetwebstack.codeplex.com/wikipage?title=Roadmap">ASP.NET Web API team future roadmap</a> to include something to help in this documentation generation. But, until they get there, we still need to document the web apis that we are creating. My initial idea is to implement the <a href="http://swagger.wordnik.com/">Swagger</a> specification and use <a href="https://github.com/wordnik/swagger-ui">Swagger-UI</a> to expose the documentation.</p>
<h3>Remember it’s a Contrib effort</h3>
<p>The goal of a Contrib effort is to group and curate extensions to the ASP.NET Web API that are created by the people using it. So, if you have an idea or created something that extends the ASP.NET Web API please, come talk to us. Send us an email on <a href="https://groups.google.com/forum/#!forum/webapicontrib">the mailing list</a>; <a href="https://github.com/WebApiContrib/WebAPIContrib/issues?sort=created&amp;direction=desc&amp;state=open">open an issue</a> to discuss a new idea; send us a pull request. Even if you don’t have an specific idea or feature that you want to discuss but are willing to help our effort, come talk to us.  The WebApiContrib is a community effort and we need your help.</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/Bm9PcxWGLfo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2012/04/04/webapicontrib/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2012/04/04/webapicontrib/</feedburner:origLink></item>
		<item>
		<title>ASP.NET Web API Routing needs a hug</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/Y1uTdEedXok/</link>
		<comments>http://pedroreys.com/2012/03/14/asp-net-web-api-routing-needs-a-hug/#comments</comments>
		<pubDate>Wed, 14 Mar 2012 04:12:50 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[WebAPIContrib]]></category>
		<category><![CDATA[ASP.NET Web API]]></category>

		<guid isPermaLink="false">http://pedroreys.com/?p=98</guid>
		<description><![CDATA[One of my goals with the WebAPIContrib is to be able to write as few code as possible in my API application and let the Contrib help me with the boring boilerplate code. Looking through the ASP.NET Web API samples, &#8230;<p class="read-more"><a href="http://pedroreys.com/2012/03/14/asp-net-web-api-routing-needs-a-hug/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>One of my goals with the <a href="https://github.com/HeadspringLabs/WebAPIContrib">WebAPIContrib</a> is to be able to write as few code as possible in my API application and let the Contrib help me with the boring boilerplate code.</p>
<p>Looking through the ASP.NET Web API samples, tutorials and blog posts out there, the first thing that jumps on my eye is the whole HttpResponseMessage noise.</p>
<div id="gist-2013364" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="n">HttpResponseMessage</span><span class="p">&lt;</span><span class="n">Person</span><span class="p">&gt;</span> <span class="n">Post</span><span class="p">(</span><span class="n">Person</span> <span class="n">person</span><span class="p">)</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>	<span class="n">_repository</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="n">person</span><span class="p">);</span></div><div class='line' id='LC4'>&nbsp;&nbsp;	<span class="kt">var</span> <span class="n">responseMessage</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpResponseMessage</span><span class="p">(</span><span class="n">person</span><span class="p">,</span> <span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">Created</span><span class="p">);</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>&nbsp;&nbsp;	<span class="n">responseMessage</span><span class="p">.</span><span class="n">Headers</span><span class="p">.</span><span class="n">Location</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Uri</span><span class="p">(</span><span class="err">“</span><span class="n">http</span><span class="p">:</span><span class="c1">//api.example.com/People/”+person.Id);</span></div><div class='line' id='LC7'>	<span class="k">return</span> <span class="n">responseMessage</span><span class="p">;</span></div><div class='line' id='LC8'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2013364/fdeaec0c04b3ec615834c63016c13234cc813f2d/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2013364#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2013364">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>I don’t want to have to write all these status code and Location Header settings all over my code. This is boring and adds noise to what actually is important on my controller action. So, my idea was to create objects to represent each status code, something similar <a href="https://github.com/mauricioaniche/restfulie.net/tree/master/Restfulie.Server/Results">to what Restfulie does</a>, and encapsulate all this noise inside these specialized HttpResponseMessages.</p>
<p>I imagined doing something similar to:</p>
<div id="gist-2013391" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">CreateResponse</span> <span class="p">:</span> <span class="n">HttpResponseMessage</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>	<span class="k">public</span> <span class="nf">CreateResponse</span><span class="p">()</span> <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">Created</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span></div><div class='line' id='LC4'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2013391/61dbfcba8ba9d1950db1898a2aba07cd1d55954c/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2013391#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2013391">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>But, in the create response I also want to set the Location Header of the new resource. As a first pass, I went with: </p>
<div id="gist-2023508" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">interface</span> <span class="n">IApiResource</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">void</span> <span class="nf">SetLocation</span><span class="p">(</span><span class="n">ResourceLocation</span> <span class="n">location</span><span class="p">);</span></div><div class='line' id='LC4'><span class="p">}</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="k">public</span> <span class="k">class</span> <span class="nc">ResourceLocation</span></div><div class='line' id='LC8'><span class="p">{</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">Uri</span> <span class="n">Location</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="k">void</span> <span class="nf">Set</span><span class="p">(</span><span class="n">Uri</span> <span class="n">location</span><span class="p">)</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">Location</span> <span class="p">=</span> <span class="n">location</span><span class="p">;</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC15'><span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'><span class="k">public</span> <span class="k">class</span> <span class="nc">CreateResponse</span> <span class="p">:</span> <span class="n">HttpResponseMessage</span></div><div class='line' id='LC18'><span class="p">{</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="nf">CreateResponse</span><span class="p">()</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">StatusCode</span> <span class="p">=</span> <span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">Created</span><span class="p">;</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="nf">CreateResponse</span><span class="p">(</span><span class="n">IApiResource</span> <span class="n">resource</span><span class="p">)</span> <span class="p">:</span><span class="k">this</span><span class="p">()</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">var</span> <span class="n">location</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ResourceLocation</span><span class="p">();</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">resource</span><span class="p">.</span><span class="n">SetLocation</span><span class="p">(</span><span class="n">location</span><span class="p">);</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">Headers</span><span class="p">.</span><span class="n">Location</span> <span class="p">=</span> <span class="n">location</span><span class="p">.</span><span class="n">Location</span><span class="p">;</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC30'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2023508/d4579f76d4c98ea8a12252bd40955e7cd43b37e2/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2023508#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2023508">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Now, in the API code I can have:</p>
<div id="gist-2023562" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">Contact</span> <span class="p">:</span> <span class="n">IApiResource</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="kt">int</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// ... other Contact Members</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="nf">SetLocation</span><span class="p">(</span><span class="n">ResourceLocation</span> <span class="n">location</span><span class="p">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">location</span><span class="p">.</span><span class="n">Location</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Uri</span><span class="p">(</span><span class="s">&quot;http://api.contoso.com/contacts/&quot;</span><span class="p">+</span><span class="n">Id</span><span class="p">);</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC10'><span class="p">}</span></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'><span class="k">public</span> <span class="k">class</span> <span class="nc">ContactsController</span> <span class="p">:</span> <span class="n">ApiController</span></div><div class='line' id='LC14'><span class="p">{</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">public</span> <span class="n">HttpResponseMessage</span> <span class="nf">Post</span><span class="p">(</span><span class="n">Contact</span> <span class="n">contact</span><span class="p">)</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//create new contact resource</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="k">new</span> <span class="nf">CreateResponse</span><span class="p">(</span><span class="n">contact</span><span class="p">);</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC20'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2023562/e919acc8aacc5a6bc312294a9d0154c31fda84f8/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2023562#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2023562">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Although this achieve my goal of setting the status code and Location header in the HttpResponseMessage I’m still not happy. Mainly because of manually building the URI of the Location. I don’t have to hardcode URLs when I can use the type system to help me with that.</p>
<h2>Embracing the type system, or not.</h2>
<p>I’m really not happy with hardcoding the URI to set the Location Header. A better way of setting that would be:</p>
<div id="gist-2023723" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="nf">SetLocation</span><span class="p">(</span><span class="n">ResourceLocation</span> <span class="n">location</span><span class="p">)</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">location</span><span class="p">.</span><span class="n">SetIn</span><span class="p">&lt;</span><span class="n">ContactsController</span><span class="p">&gt;(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Get</span><span class="p">(</span><span class="n">Id</span><span class="p">));</span></div><div class='line' id='LC4'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2023723/80f76e70d7774be4955d63c9379fbeaf689f6b0b/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2023723#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2023723">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>With that, all I would have to do is generate the URL for that controller action and set it to the Location Header. Piece of cake, it’s just use the built-in UrlHelper. Or, that’s what I thought.</p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.web.http.routing.urlhelper(v=vs.108).aspx">System.Web.<strong>Http</strong>.Routing.UrlHelper</a> has a <a href="http://msdn.microsoft.com/en-us/library/hh834562(v=vs.108).aspx">Route</a> method that returns an URL for a set of route values. OK, so at first glance I just need to translate my Expression&lt;Action&lt;TController&gt;&gt; in a dictionary of route values. This is not a problem, <a href="http://mvccontrib.codeplex.com/SourceControl/changeset/view/bb5feec203bb#src%2fMVCContrib%2fActionResults%2fRedirectToRouteResult.cs">MVCContrib, for example, uses</a> a <a href="http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266392">helper from the MVCFutures assembly</a> to do this. As I’m working in the WebAPIContrib, I didn’t want to take a dependency in the MVCFutures just for this. I ended up coding the reflection part myself.</p>
<p>OK, no I have a RouteValueDictionary, to get the URL back is just call urlHelper.Route(routeValues), right? Not so quickly.</p>
<h2>Y’all gotta know the names. All the names</h2>
<p>The Route method on UrlHelper is not like the Action method on it’s System.Web.MVC sibling (more on this Mvc x Http later). As you can see in the <a href="http://msdn.microsoft.com/en-us/library/hh834562(v=vs.108).aspx">MSDN documentation</a>, the Route method signature is:</p>
<div id="gist-2033643" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="kt">string</span> <span class="nf">Route</span><span class="p">(</span></div><div class='line' id='LC2'>	<span class="kt">string</span> <span class="n">routeName</span><span class="p">,</span></div><div class='line' id='LC3'>	<span class="n">IDictionary</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="n">Object</span><span class="p">&gt;</span> <span class="n">routeValues</span></div><div class='line' id='LC4'><span class="p">)</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2033643/9929535a2ca6ad6d463e5a09c94a7e78aecf292f/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2033643#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/2033643">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Together with the route values you also have to supply the route name. As I’m building a library for others to use while building their APIs, I don’t know which route to use. My first thought was: I’m just going to iterate over the HttpRouteCollection and the first URL I get back would win. That’s when I started learning more about the ASP.NET Web API routing implementation than I was wanting to.</p>
<h2>No foreach for you</h2>
<p>When I tried to iterate over the HttpRouteCollection, the following exception was thrown:</p>
<div id="gist-2033770" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>System.NotSupportedException was caught</div><div class='line' id='LC2'>&nbsp;&nbsp;Message=This operation is only supported by directly calling it on &#39;RouteCollection&#39;.</div><div class='line' id='LC3'>&nbsp;&nbsp;Source=System.Web.Http.WebHost</div><div class='line' id='LC4'>&nbsp;&nbsp;StackTrace:</div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.GetEnumerator()</div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at WebApiContrib.Internal.RoutingHelper.GetUriFor(RouteValueDictionary routeValues, HttpControllerContext controllerContext) in C:\dev\WebAPIContrib\src\WebApiContrib\Internal\RoutingHelper.cs:line 42</div><div class='line' id='LC7'>&nbsp;&nbsp;InnerException: </div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2033770/d2caba81e26f328bbf092496855d6ec19998af0b/gistfile1.txt" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2033770#file_gistfile1.txt" style="float:right;margin-right:10px;color:#666">gistfile1.txt</a>
            <a href="https://gist.github.com/2033770">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Checking on Google, I found out that I had to get a read lock first, before iterating over the collection. This is done through the <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.getreadlock.aspx">GetReadLock</a> method that returns a disposable lock object. <code>:SadTrombone:</code> Fooled one more time by the Mvc vs. Http identity issues. Only <a href="http://msdn.microsoft.com/en-us/library/cc680101.aspx">System.Web.Routing.RouteCollection</a> has the GetReadLock method. The <a href="http://msdn.microsoft.com/en-us/library/system.web.http.httproutecollection(v=vs.108).aspx">HttpRouteCollection</a> counterpart doesn’t have it.&#160; So, I had to fall back to for loops to get the routes out of the HttpRouteCollection.</p>
<p>Then, another surprise. To refresh your memory, we are doing all this looping things in order to get the route name so that we can use the UrlHelper to get the Location header URI. So, after I was able to get a route object instance, I found out that there is no way to get it’s name. Yeap, you create a route with a name. The UrlHelper asks you for a route name. You can even check in the collection if there are any routes with a given name. But you can’t get the name from a route instance. With dotpeek’s help I figured out that the name is used as the key in the private dictionary that the HttpRouteCollection wraps. But the HttpRouteCollection doesn’t make the Keys property of the dictionaty available to the outside world. That’s it. There is no way for you to programmatically find a routes name.</p>
<h2>Ah, the ControllerContext</h2>
<p>At this point I was already pretty frustrated. I was working on this during the Dallas Day of .Net and I was afraid I wouldn&#8217;t be able to keep cursing only in my head anymore. Actually I believe I said one or two “WTF!” loudly. Anyways, I gave up the whole let’s-find-out-the-route-name-thing and decided to hard code the default one instead. Just so that I could at least see the thing working. </p>
<p>To my despair, I realized that the System.Web.Http.Routing.UrlHelper depends on the HttpControllerContext, not in the RequestContext as System.Web.Mvc.UrlHelper. As I can’t simply create, or at least not as easily, an instance of the HttpControllerContext as <a href="https://github.com/mauricioaniche/restfulie.net/blob/master/Restfulie.Server/Marshalling/UrlGenerators/AspNetMvcUrlGenerator.cs#L14">I can create one</a> of the RequestContext, I just changed the constructor of the CreateResponse to also include the HttpControllerContext. </p>
<div id="gist-2033950" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="n">HttpResponseMessage</span><span class="p">&lt;</span><span class="n">Contact</span><span class="p">&gt;</span> <span class="n">Post</span><span class="p">(</span><span class="n">Contact</span> <span class="n">contact</span><span class="p">)</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">this</span><span class="p">.</span><span class="n">repository</span><span class="p">.</span><span class="n">Post</span><span class="p">(</span><span class="n">contact</span><span class="p">);</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="k">new</span> <span class="n">CreateResponse</span><span class="p">&lt;</span><span class="n">Contact</span><span class="p">&gt;(</span><span class="n">contact</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">ControllerContext</span><span class="p">);</span></div><div class='line' id='LC6'><span class="p">}</span></div><div class='line' id='LC7'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2033950/b80cfec9c1d0faa832863e0e8b92899ada8b4ece/response.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2033950#file_response.cs" style="float:right;margin-right:10px;color:#666">response.cs</a>
            <a href="https://gist.github.com/2033950">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>I’m definitely not happy with this and I won’t include any of it, as it is, in the WebAPIContrib.</p>
<h2>Least Surprise who?</h2>
<p>Let’s be clear: this whole thing of System.Web.Mvc vs. System.Web.Http is confusing as hell. Things have the same name but are different types. The api for those types are different. They behave differently. I can see a lot of people struggling as I did when trying to use whatever they are using in their MVC projects in a Web API one.</p>
<h2>But the Web API is still in beta and this is what a beta is for, right?</h2>
<p>Yes, the ASP.NET Web API is still in Beta and I expect a lot of the library api to change. <a href="https://twitter.com/#!/frystyk/status/178704676152283136">As Henrik Nielsen asked me to do</a>, I’ll register the issues I had on user voice. And I can only hope they will fix it. Or maybe accept a pull request ;-)</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/Y1uTdEedXok" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2012/03/14/asp-net-web-api-routing-needs-a-hug/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2012/03/14/asp-net-web-api-routing-needs-a-hug/</feedburner:origLink></item>
		<item>
		<title>Extending ASP.NET Web API  Content Negotiation</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/vaiIlLcphNo/</link>
		<comments>http://pedroreys.com/2012/02/17/extending-asp-net-web-api-content-negotiation/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 14:00:00 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[ASP.NET Web API]]></category>
		<category><![CDATA[conneg]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://pedroreys.com/?p=89</guid>
		<description><![CDATA[The ASP.NET team released the beta version of the ASP.NET Web API, previously known as WCF Web API, as part of the beta release of ASP.NET MVC 4. Having experience implementing web APIs with Restfulie, I was curious and decided &#8230;<p class="read-more"><a href="http://pedroreys.com/2012/02/17/extending-asp-net-web-api-content-negotiation/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>The ASP.NET team released the beta version of the <a href="http://www.asp.net/web-api">ASP.NET Web API</a>, previously known as WCF Web API, as part of the <a href="http://www.asp.net/vnext/overview/downloads">beta release of ASP.NET MVC 4</a>. Having experience implementing web APIs with <a href="http://restfulie.caelum.com.br/">Restfulie</a>, I was curious and decided to check how the ASP.NET Web API works to compare it with Restfulie.</p>
<p>The first thing I noticed was a difference in the Content Negotiation implementation. I don’t intend to do a full comparison here, but to describe how to use one of the extension points in the Web API to add the behavior that I wanted.</p>
<p>If you are not interested in in the reasons why the Content Negotiation implementation differs, and why I prefer the Restfulie one and just want to see DA CODEZ, feel free to jump to the “Message Handlers to the Rescue” part.</p>
<h2>Content Negotiation</h2>
<p>Content Negotiation, simply put, is the process of figuring out what is the media-type that needs to be used in the Resource Representation that is going to be returned in a HTTP Response. This negotiation between client and server happens through the interpretation of the HTTP Accept Header values.</p>
<p>When a client makes a request, if the client wants to specify a set of media-types that it accepts the resource to be formatted into, then these media types should be included in the Accept Header. All the semantics and options regarding the usage of the Accept header can be found on <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">section 14.1</a> of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">RFC 2616</a> (HTTP specification). In the Accept Header definition there is a part that reads:</p>
<blockquote><p>If no Accept header field is present, then it is assumed that the client accepts all media types. If an Accept header field is present, and if the server cannot send a response which is acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response.</p></blockquote>
<p>The SHOULD key word in the RFC 2616, according to <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.2">section 1.2</a> of the RFC, is to be interpreted as described in the <a href="http://www.ietf.org/rfc/rfc2119.txt">RFC 2119</a>. The description of SHOULD in this RFC is:</p>
<blockquote><p>SHOULD   This word, or the adjective &#8220;RECOMMENDED&#8221;, mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.</p></blockquote>
<p>With this definition, I interpret the Accept Header behavior as: unless you have a specific reason not to, if the HTTP Request contains an Accept Header and the server does not support the requested media-type, a 406 – Not Acceptable response should be returned.  Returning other Status Code might be OK, as it’s not mandatory to return 406, but this should be the exception, not the default behavior.</p>
<h2>ASP.NET Web API Content Negotiation Implementation</h2>
<p>The namespace System.Net.Http.Formatting has a MediaTypeFormatter class whose instances are used by the Web API (I’m going to omit the ASP.NET part from now on) to format the resource representation to a specific media-type.</p>
<p>The Web API ships with JsonMediaTypeFormatter and XmlMediaTypeFormatter implementations. And it defaults to the JSON formatter when no specific media-type is requested. So, if the Accept Header is not included in the HTTP Request, Web API will use the JSON formatter to format the Resource Representation that is going to be returned.</p>
<p>You can add your own MediaType formatter by adding your formatter implementation to the MediaTypeFormatter collection of the HTTPConfiguration object in the GlobalConfiguration class.</p>
<h2>It seems like something is not right here</h2>
<p>While I was playing with the Web API, I decided to test the behavior of the Content Negotiation implementation in the scenario where the media-type in the Accept Header is not accepted by the server. That is, when the HTTP Request Accept Header specifies a media-type that the Web API doesn’t have a MediaTypeFormatter implementation that can handle it. By the definition described in the Content Negotiation section above, I expected to receive a 406 response back. To my surprise, I got a 200 – OK response back with a Resource Representation with text/json contant-type. Web API fell back to the default MediaTypeFormatter instead of returning 406.</p>
<div id="gist-1849567" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>C:\dev&gt; curl -v -H &quot;Accept: application/some_unknown_media_type&quot; localhost:1705/api/values</div><div class='line' id='LC2'>* About to connect() to localhost port 1705 (#0)</div><div class='line' id='LC3'>*   Trying 127.0.0.1... connected</div><div class='line' id='LC4'>* Connected to localhost (127.0.0.1) port 1705 (#0)</div><div class='line' id='LC5'>&gt; GET /api/values HTTP/1.1</div><div class='line' id='LC6'>&gt; User-Agent: curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3</div><div class='line' id='LC7'>&gt; Host: localhost:1705</div><div class='line' id='LC8'>&gt; Accept: application/some_unknown_media_type</div><div class='line' id='LC9'>&gt;</div><div class='line' id='LC10'>&lt; HTTP/1.1 200 OK</div><div class='line' id='LC11'>&lt; Server: ASP.NET Development Server/10.0.0.0</div><div class='line' id='LC12'>&lt; Date: Fri, 17 Feb 2012 01:27:42 GMT</div><div class='line' id='LC13'>&lt; X-AspNet-Version: 4.0.30319</div><div class='line' id='LC14'>&lt; Transfer-Encoding: chunked</div><div class='line' id='LC15'>&lt; Cache-Control: no-cache</div><div class='line' id='LC16'>&lt; Pragma: no-cache</div><div class='line' id='LC17'>&lt; Expires: -1</div><div class='line' id='LC18'>&lt; Content-Type: application/json; charset=utf-8</div><div class='line' id='LC19'>&lt; Connection: Close</div><div class='line' id='LC20'>&lt;</div><div class='line' id='LC21'>[&quot;value1&quot;,&quot;value2&quot;]* Closing connection #0</div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1849567/5cbcef5f6a4e11e237defac64067abc7581426e6/gistfile1.txt" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1849567#file_gistfile1.txt" style="float:right;margin-right:10px;color:#666">gistfile1.txt</a>
            <a href="https://gist.github.com/1849567">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>This was a surprise to me, so I filled a bug report for this in the Web API Forum. <a href="http://en.wikipedia.org/wiki/Henrik_Frystyk_Nielsen">Henrik Frystyk Nielsen</a> replied saying:</p>
<blockquote><p>It&#8217;s a reasonable to respond either with a 200 or with a 406 status code in this case. At the moment we err on the side of responding with a 2xx but I completely agree that there are sceanarios where 406 makes a lot of sense. Ultimately we need some kind of switch for making it possible to respond with 406 but it&#8217;s not there yet.</p></blockquote>
<p>Fine. The 406 response is not mandatory, the Web API is still in beta. I understand the 406 handling not being there yet. And, the last thing I want to do is to get into a discussion of RFC semantics with one of the authors of the specification  :P</p>
<h2>Message Handlers to the Rescue</h2>
<p>When a HTTP Request is made to a Web API application, that request is passed  to an instance of the HttpServer class. This class derives from HttpMessageHandler and it will delegate the processing of the HTTP request to the next handler present in the HttpConfiguration.MessageHandlers collection. All handlers in the collection will be called to process the request, the last one being the HttpControllerDispatcher that, as you can tell, will dispatch the call to an Action in a Controller. <a href="http://mvc.fubu-project.org/">FubuMVC</a> <a href="http://codebetter.com/jeremymiller/2011/01/09/fubumvcs-internal-runtime-the-russian-doll-model-and-how-it-compares-to-asp-net-mvc-and-openrasta/">Behavior Chains</a> implements an approach similar to this. (Fubu guys, I know it’s not the same thing, but y’all get my point :))</p>
<p>With that said, in order to return a response with 406 status code, what I need to do is implement a HttpMessageHandler that does that.</p>
<div id="gist-1850200" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">NotAcceptableConnegHandler</span> <span class="p">:</span> <span class="n">DelegatingHandler</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>	<span class="k">private</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">allMediaTypesRange</span> <span class="p">=</span> <span class="s">&quot;*/*&quot;</span><span class="p">;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>	<span class="k">protected</span> <span class="k">override</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span> <span class="n">SendAsync</span><span class="p">(</span><span class="n">HttpRequestMessage</span> <span class="n">request</span><span class="p">,</span> <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">)</span></div><div class='line' id='LC6'>	<span class="p">{</span></div><div class='line' id='LC7'>		<span class="kt">var</span> <span class="n">acceptHeader</span> <span class="p">=</span> <span class="n">request</span><span class="p">.</span><span class="n">Headers</span><span class="p">.</span><span class="n">Accept</span><span class="p">;</span></div><div class='line' id='LC8'>		<span class="k">if</span> <span class="p">(!</span><span class="n">acceptHeader</span><span class="p">.</span><span class="n">Any</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">MediaType</span> <span class="p">==</span> <span class="n">allMediaTypesRange</span><span class="p">))</span></div><div class='line' id='LC9'>		<span class="p">{</span></div><div class='line' id='LC10'>			<span class="kt">var</span> <span class="n">hasFormetterForRequestedMediaType</span> <span class="p">=</span> <span class="n">GlobalConfiguration</span></div><div class='line' id='LC11'>								<span class="p">.</span><span class="n">Configuration</span></div><div class='line' id='LC12'>						                <span class="p">.</span><span class="n">Formatters</span></div><div class='line' id='LC13'>								<span class="p">.</span><span class="n">Any</span><span class="p">(</span><span class="n">formatter</span> <span class="p">=&gt;</span> <span class="n">acceptHeader</span><span class="p">.</span><span class="n">Any</span><span class="p">(</span><span class="n">mediaType</span> <span class="p">=&gt;</span> <span class="n">formatter</span><span class="p">.</span><span class="n">SupportedMediaTypes</span><span class="p">.</span><span class="n">Contains</span><span class="p">(</span><span class="n">mediaType</span><span class="p">)));</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'>			<span class="k">if</span> <span class="p">(!</span><span class="n">hasFormetterForRequestedMediaType</span><span class="p">)</span></div><div class='line' id='LC16'>				<span class="k">return</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;.</span><span class="n">Factory</span><span class="p">.</span><span class="n">StartNew</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="n">HttpResponseMessage</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">NotAcceptable</span><span class="p">));</span></div><div class='line' id='LC17'>		<span class="p">}</span></div><div class='line' id='LC18'>		<span class="k">return</span> <span class="k">base</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">);</span></div><div class='line' id='LC19'>	<span class="p">}</span>   </div><div class='line' id='LC20'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1850200/5b2c057ff96271119eff8c80df53a58c7f86da81/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1850200#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1850200">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>With the handler created, the next step is to configure Web API to include this handler in the HTTP Request processing pipeline. To do so, in the Application_Start method in the Global.asax , add an instance of the new handler to the MessageHandlers collection.</p>
<div id="gist-1850239" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">protected</span> <span class="k">void</span> <span class="nf">Application_Start</span><span class="p">()</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//Default Registration and configuration stuff</span></div><div class='line' id='LC4'>	<span class="n">AreaRegistration</span><span class="p">.</span><span class="n">RegisterAllAreas</span><span class="p">();</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>	<span class="n">RegisterGlobalFilters</span><span class="p">(</span><span class="n">GlobalFilters</span><span class="p">.</span><span class="n">Filters</span><span class="p">);</span></div><div class='line' id='LC7'>	<span class="n">RegisterRoutes</span><span class="p">(</span><span class="n">RouteTable</span><span class="p">.</span><span class="n">Routes</span><span class="p">);</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>	<span class="n">BundleTable</span><span class="p">.</span><span class="n">Bundles</span><span class="p">.</span><span class="n">RegisterTemplateBundles</span><span class="p">();</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//Call to a Configure method created to add message handlers to the Request pipeline</span></div><div class='line' id='LC12'>	<span class="n">Configure</span><span class="p">(</span><span class="n">GlobalConfiguration</span><span class="p">.</span><span class="n">Configuration</span><span class="p">);</span></div><div class='line' id='LC13'><span class="p">}</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'><span class="k">static</span> <span class="k">void</span> <span class="nf">Configure</span><span class="p">(</span><span class="n">HttpConfiguration</span> <span class="n">configuration</span><span class="p">)</span></div><div class='line' id='LC16'><span class="p">{</span></div><div class='line' id='LC17'>	<span class="n">configuration</span><span class="p">.</span><span class="n">MessageHandlers</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="k">new</span> <span class="n">NotAcceptableConnegHandler</span><span class="p">());</span></div><div class='line' id='LC18'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1850239/96a11484aa921b7f7b4b7bf37d7b9b2e4a706f93/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1850239#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1850239">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>With the application configured to use the custom handler, when that same request is made, a response with 406 Status Code is now returned.</p>
<div id="gist-1850262" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>C:\dev&gt; curl -v  -H &quot;Accept: text/unknown_media_type&quot; localhost:1705/api/values</div><div class='line' id='LC2'>* About to connect() to localhost port 1705 (#0)</div><div class='line' id='LC3'>*   Trying 127.0.0.1... connected</div><div class='line' id='LC4'>* Connected to localhost (127.0.0.1) port 1705 (#0)</div><div class='line' id='LC5'>&gt; GET /api/values HTTP/1.1</div><div class='line' id='LC6'>&gt; User-Agent: curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3</div><div class='line' id='LC7'>&gt; Host: localhost:1705</div><div class='line' id='LC8'>&gt; Accept: text/unknown_media_type</div><div class='line' id='LC9'>&gt;</div><div class='line' id='LC10'>&lt; HTTP/1.1 406 Not Acceptable</div><div class='line' id='LC11'>&lt; Server: ASP.NET Development Server/10.0.0.0</div><div class='line' id='LC12'>&lt; Date: Fri, 17 Feb 2012 02:59:58 GMT</div><div class='line' id='LC13'>&lt; X-AspNet-Version: 4.0.30319</div><div class='line' id='LC14'>&lt; Cache-Control: no-cache</div><div class='line' id='LC15'>&lt; Pragma: no-cache</div><div class='line' id='LC16'>&lt; Expires: -1</div><div class='line' id='LC17'>&lt; Content-Length: 0</div><div class='line' id='LC18'>&lt; Connection: Close</div><div class='line' id='LC19'>&lt;</div><div class='line' id='LC20'>* Closing connection #0</div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1850262/4cf5496a0220b04a4ca7ab720d6bb4aed22b3bd9/gistfile1.txt" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1850262#file_gistfile1.txt" style="float:right;margin-right:10px;color:#666">gistfile1.txt</a>
            <a href="https://gist.github.com/1850262">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>The power of Russian Dolls</h2>
<p>The Web API HTTP Request pipeline provides a powerful extension point to introduce specialized, SRP adherent, handlers keeping the controller action implementation simple and focused.</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/vaiIlLcphNo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2012/02/17/extending-asp-net-web-api-content-negotiation/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2012/02/17/extending-asp-net-web-api-content-negotiation/</feedburner:origLink></item>
		<item>
		<title>Installing Less.css on OSX Lion</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/bYKDWq8fTqM/</link>
		<comments>http://pedroreys.com/2012/02/03/installing-less-css-on-osx-lion/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 02:42:50 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[less]]></category>
		<category><![CDATA[lion]]></category>
		<category><![CDATA[npm]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://pedroreys.com/?p=80</guid>
		<description><![CDATA[Today I was following the instructions to upgrade to the latest version of the Twitter Bootstrap. It&#8217;s pretty straight forward. It is really awesome, actually. All you have to do is: Open the terminal, pull the changes, run make. But, &#8230;<p class="read-more"><a href="http://pedroreys.com/2012/02/03/installing-less-css-on-osx-lion/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Today I was following the instructions to upgrade to the latest version of the Twitter Bootstrap.</p>
<p>It&#8217;s pretty straight forward. It is really awesome, actually. All you have to do is: Open the terminal, pull the changes, run <code>make</code>.</p>
<p>But, Twitter Bootstrap uses Less.css, so one of the steps of the update script is to compile the <code>.less</code> files into <code>.css</code>. I didn&#8217;t have less compiler installed on my MacBook Pro, so instead of successfully upgrading the Bootstrap, I got this on my terminal:</p>
<p><img src="http://f.cl.ly/items/33232j3z201O3B0s2q3q/Screen%20Shot%202012-02-02%20at%208.16.59%20PM.png" alt="lessc: command not found" /></p>
<p>So, my first reaction was to try installing less using Homebrew:</p>
<p><img src="http://f.cl.ly/items/260U2t3b1L3Q392G1q1h/Screen%20Shot%202012-02-02%20at%208.19.46%20PM.png" alt="Homebrew doesn't have a formula for less.css" /></p>
<p>Dang it. There is not Homebrew formula for Less. I&#8217;ll have to open my browser to install a software, damn it. So I headed to <a href="http://lesscss.org/">Less.css</a> website and saw that the easiest way to install the compiler to be used on the server side is via the node package manager, <a title="package manager for node" href="http://npmjs.org/">npm</a>. Then I did: <code>npm install less</code></p>
<p><img src="http://f.cl.ly/items/043Q440w3e2w2q3o2K2f/Screen%20Shot%202012-02-02%20at%208.27.12%20PM.png" alt="npm installed less" /></p>
<p>All right, now let&#8217;s try running make again.</p>
<p><img src="http://f.cl.ly/items/3Q363v1l0l2I0Y0a0v3B/Screen%20Shot%202012-02-02%20at%208.28.58%20PM.png" alt="less not found again" /></p>
<p>Ok. It&#8217;s still not found. Maybe installing it globally will solve the problem: <code>npm install less --global</code></p>
<p><img src="http://f.cl.ly/items/1o061I3E461t2S2t1D0Z/Screen%20Shot%202012-02-02%20at%208.36.59%20PM.png" alt="npm install less with global option" /></p>
<p>All right, now that less is installed globally, let&#8217;s try running <code>make</code> again to update Twitter Bootstrap.</p>
<p><img src="http://f.cl.ly/items/0O2u2w0O3h1g1t0d0U2t/Screen%20Shot%202012-02-02%20at%208.38.25%20PM.png" alt="Bootstrap upgraded succesfully. Yay!" /></p>
<p>Yay, it worked. The <code>--global</code> option did the trick.</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/bYKDWq8fTqM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2012/02/03/installing-less-css-on-osx-lion/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2012/02/03/installing-less-css-on-osx-lion/</feedburner:origLink></item>
		<item>
		<title>Running TeamCity on EC2</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/kTeId5DibjU/</link>
		<comments>http://pedroreys.com/2011/05/23/running-teamcity-on-ec2/#comments</comments>
		<pubDate>Mon, 23 May 2011 17:19:07 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[tutorial]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[TeamCity]]></category>

		<guid isPermaLink="false">http://blog.pedroreys.com/2011/05/23/running-teamcity-on-ec2/</guid>
		<description><![CDATA[&#160; One of Headspring’s core mantras is to outsource everything that is not part of our core business. We are true believers on running the business in the cloud. We are even giving a talk about it. We use many &#8230;<p class="read-more"><a href="http://pedroreys.com/2011/05/23/running-teamcity-on-ec2/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>One of Headspring’s core mantras is to outsource everything that is not part of our core business. We are true believers on running the business in the cloud. <a href="http://www.eventbrite.com/event/1707145117">We are even giving a talk about it</a>. We use many cloud service providers on a daily basis. We use <a href="http://www.google.com/apps/intl/en/business/#utm_campaign=en&amp;utm_source=en-ha-na-us-bk&amp;utm_medium=ha&amp;utm_term=google%20apps">Google Apps</a> for Email, Calendar, Voice and Intranet. We use <a href="http://www.salesforce.com/">Salesforce</a> as our CRM. We use <a href="http://bitbucket.org">BitBucket</a> to host our source code.</p>
<p>We use all this services to do things that are necessary in order to run the company but that we don’t want to manage or build ourselves. So, we decided to do the same thing with our build system. As we were using <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> as our CI server and it has <a href="http://www.jetbrains.com/teamcity/features/amazon_ec2.html">integration with EC2 out of the box</a> we decided to go with EC2.</p>
<p>First, TeamCity is composed of two pieces. The build server, that runs TeamCity’s dashboard and the build agents, that actually run the builds. As TeamCity Server is a Java application, a small Linux instance on EC2 is enough to run it. The server itself won’t leverage the Elastic features on EC2, but having the server running on the same region and availability zone as the agents is important in order to avoid <a href="http://aws.amazon.com/ec2/pricing/">Data Transfer charges</a>.</p>
<p>&nbsp;</p>
<h2>Server</h2>
<p>&nbsp;</p>
<p>To install TeamCity server on Linux, follow this steps:</p>
<p><strong>1)</strong> <a href="http://www.jetbrains.com/teamcity/download/index.html#linux">Get TeamCity from JetBrains</a>.</p>
<p><strong>2)</strong> Unpack the file Teamcity&lt;version number&gt;.tar.gz as documented in the <a href="http://confluence.jetbrains.net/display/TCD6/Installing+and+Configuring+the+TeamCity+Server#InstallingandConfiguringtheTeamCityServer-InstallingTeamCitybundledwithTomcatservletcontainer%28Linux%2CMacOSX%2CWindows%29">docs</a>.</p>
<p><strong>3)</strong> Elevate your privileges to root:</p>
<p><span style="font-family: 'Courier New';"> &gt; sudo su</span></p>
<p>This is needed because we want the server to listen to port 80 and ports below 1024 can only be listened by the root user.</p>
<p><strong>4)</strong> Install Sun/Oracle JDK.</p>
<p>EC2 instance is a RedHat distribution, that uses OpenJDK by default. To the cloud integration on TeamCity to work properly, <a href="http://youtrack.jetbrains.net/issue/TW-14961">it needs Sun/Oracle’s JDK</a>.</p>
<p><strong>5)</strong> With Sun/Oracle’s JDK installed, set the JAVA_HOME environment variable to use it, instead of OpenJDK:</p>
<p><span style="font-family: 'Courier New';"> &gt; JAVA_HOME=/usr/java/jdk&lt;version&gt;</span></p>
<p><strong>6)</strong> <a href="http://confluence.jetbrains.net/display/TCD6/Installing+and+Configuring+the+TeamCity+Server#InstallingandConfiguringtheTeamCityServer-ChangingServerPort">Change TeamCity server port to 80</a> (if you need to)</p>
<p><strong>7)</strong> Start the Server. On TeamCity’s bin directory, run:</p>
<p><span style="font-family: 'Courier New';">&gt; ./teamcity-server.sh start</span></p>
<p><span style="font-family: 'Courier New';"> </span></p>
<p>That’s it. The server should be up and running. If you hit instance’s public URL on your browser, after the server finishes starting up you should get a screen to accept TeamCity’s EULA.</p>
<p><a title="TeamCIty_EULA" href="http://www.flickr.com/photos/22313104@N04/5750784189/"><img style="display: block; float: none; margin-left: auto; margin-right: auto;" src="http://farm3.static.flickr.com/2011/5750784189_1158b37dee.jpg" border="0" alt="TeamCIty_EULA" /></a></p>
<p>After accepting the EULA, you will be prompted to create an Administrator Account. With the Administrator Account created, TeamCity server is installed and running properly.</p>
<h2>Installing the Build Agent</h2>
<p>&nbsp;</p>
<p>With the Server up and running it’s time to create the agents that will run the builds.</p>
<p>To do so, first launch a instance ( I’m going to use a Windows one as we are doing .NET here) on EC2 and configure it to work as a TeamCity agent. In our case, we chose to use a Large Windows x64 instance.</p>
<p>As it’s necessary to remote into the instance to configure it to run as a TeamCity agent, wait approximately 15 minutes after the instance is launched to Remote into it, otherwise you won’t be able to get the password from AWS.</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5751337652/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="Wait_for_instance[1]" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/Wait_for_instance1.png" border="0" alt="Wait_for_instance[1]" width="381" height="127" /></a></p>
<p>With the instance credentials, follow this steps:</p>
<p><strong>1)</strong> Remote into the instance</p>
<p><strong>2)</strong> Open the browser and go to TeamCity Server URL. After authenticating, go to the Agents tab and download MS Windows Installer.</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5750832543/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="Agents_Tab" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/Agents_Tab.png" border="0" alt="Agents_Tab" width="576" height="342" /></a></p>
<p><strong>3)</strong> Run the installer. After the agent is installed, a form to “Configure Build Agent Properties” will be prompted. Change the <strong>serverUrl </strong>property to point to the correct URI.</p>
<p><strong>4)</strong> TeamCity agent-server communication uses port 9090 by default, unless you’ve changed it when configuring Build Agent properties on the previous step. So, in order to enable the communication between agent and server, create a inbound rule on Windows firewall to allow communication trough port 9090.</p>
<p><strong>5) </strong>If everything is configured properly, you should have a Unauthorized agent showing up on TeamCity Server.</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5751442728/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="unauthorized_agent" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/unauthorized_agent.png" border="0" alt="unauthorized_agent" width="513" height="325" /></a></p>
<p><strong>6)</strong> Authorize the agent and check that it’s capable of running properly your builds.</p>
<p>&nbsp;</p>
<h2>Making the Build Agent Elastic</h2>
<p>&nbsp;</p>
<p>Right now we have a EC2 based TeamCity server and a TeamCity Agent running on a EC2 instance but it’s not leveraging the Elastic features of TeamCity yet. To enable Elastic, Cloud Based, build agents one has to create a AMI image of the instance  running the Agent.</p>
<p><strong>1) </strong>On AWS, select the running instances and right-click on the instance running the Build Agent. On the context menu, select “Create Image (EBS AMI)”</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5750940659/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="Create_Image_EBS[4]" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/Create_Image_EBS4.png" border="0" alt="Create_Image_EBS[4]" width="244" height="143" /></a></p>
<p><strong>2)</strong> When the AMI becomes available on aws, go to Cloud Tab under TeamCity Agents page:</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5750956671/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="cloud" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/cloud.png" border="0" alt="cloud" width="538" height="213" /></a></p>
<p><strong>3)</strong> On the configuration page, create a new Cloud Profile. As of now, the only option of Cloud Type is Amazon EC2. Choose your location and availability zone to match the ones the server instance is running in order to avoid extra Data Transfer costs.</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5751563606/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="cloud_profile[5]" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/cloud_profile5.png" border="0" alt="cloud_profile[5]" width="403" height="372" /></a></p>
<p>&nbsp;</p>
<p>That’s it. TeamCity is configured to use Elastic Build Agents.</p>
<p>When a build is triggered, if there are no agents available to run it, the build will be placed on the Build Queue. A instance will be requested to EC2. It will take approximately 10 minutes for the instance to be running and authorized as a Build Agent on TeamCity.</p>
<p><a href="http://www.flickr.com/photos/22313104@N04/5751144159/"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px; border: 0px;" title="instance_starting" src="http://pedroreys.com/blog/wp-content/uploads/2011/05/instance_starting.png" border="0" alt="instance_starting" width="538" height="138" /></a></p>
<p>My goal with this post was to document the process of migrating Headspring’s build system to leverage EC2 features. I hope this helps not only me.</p>
<p>One last thing, can you do me a favor and vote for <a href="http://youtrack.jetbrains.net/issue/TW-16490">this TeamCity feature request</a>?</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/kTeId5DibjU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2011/05/23/running-teamcity-on-ec2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2011/05/23/running-teamcity-on-ec2/</feedburner:origLink></item>
		<item>
		<title>HotFix for Checkdisk hanging at 1 sec</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/AtdLQmiSEws/</link>
		<comments>http://pedroreys.com/2010/07/30/hotfix-for-checkdisk-hanging-at-1-sec/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 03:22:07 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[CheckDisk]]></category>
		<category><![CDATA[HotFix]]></category>
		<category><![CDATA[KB]]></category>

		<guid isPermaLink="false">http://blog.pedroreys.com/2010/07/30/hotfix-for-checkdisk-hanging-at-1-sec/</guid>
		<description><![CDATA[I have a Dell Studio XPS 1640 running Windows 7 Home Premium x64. Yesterday it crashed (sigh) and when I rebooted the check disk was triggered. To my, not pleasant, surprise, Check Disk hanged at 1 sec left on the &#8230;<p class="read-more"><a href="http://pedroreys.com/2010/07/30/hotfix-for-checkdisk-hanging-at-1-sec/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>I have a Dell Studio XPS 1640 running Windows 7 Home Premium x64. </p>
<p>Yesterday it crashed (sigh) and when I rebooted the check disk was triggered. To my, not pleasant, surprise, Check Disk hanged at 1 sec left on the countdown for pressing a key to skip the disk check. Doing a hard reboot several times I was able to start windows again.</p>
<p>Well, after some googling I found the <a href="http://support.microsoft.com/kb/975778">HOTFIX KB 975778</a> that solved the issue like a charm for me.</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/AtdLQmiSEws" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2010/07/30/hotfix-for-checkdisk-hanging-at-1-sec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2010/07/30/hotfix-for-checkdisk-hanging-at-1-sec/</feedburner:origLink></item>
		<item>
		<title>Handling Content Type as we should, through HTTP Headers</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/EAMscLIz6Q0/</link>
		<comments>http://pedroreys.com/2010/05/10/handling-content-type-as-we-should-through-http-headers/#comments</comments>
		<pubDate>Mon, 10 May 2010 02:08:15 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Content-Type]]></category>
		<category><![CDATA[HTML Header]]></category>
		<category><![CDATA[Json]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.pedroreys.com/2010/05/10/handling-content-type-as-we-should-through-http-headers/</guid>
		<description><![CDATA[In the previous post I spiked a solution to return different result types depending on a requested format. While the solution I came up with was sufficient to address the points issued on a thread at .NetArchitects, Eric Hexter hit &#8230;<p class="read-more"><a href="http://pedroreys.com/2010/05/10/handling-content-type-as-we-should-through-http-headers/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://blog.pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/" target="_blank">previous post</a> I spiked a solution to return different result types depending on a requested format. While the solution I came up with was sufficient to address the points issued on a thread at .NetArchitects, <a href="http://www.lostechies.com/blogs/hex/" target="_blank">Eric Hexter</a> hit the nail on the head with the following <a href="http://twitter.com/ehexter/status/9712355635" target="_blank">tweet</a>:</p>
<blockquote><p>@<a href="http://twitter.com/pedroreys">pedroreys</a> nice post on the formatter. I would consider http headers instead of routing, although that is hard to manually debug</p>
</blockquote>
<p>The right way to specify the types which are accepted for the response is by using the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html" target="_blank">Accept</a> request-header. It’s been a while since Eric’s tweet, but here is the solution I came up with.</p>
<p>Lemme first define the expectations I defined:</p>
<p>If the Accept header of the request</p>
<p>- Contains <font face="Courier New">“text/html”</font> a <font face="Courier New">ViewResult</font> should be returned.</p>
<p>- Contains <font face="Courier New">“application/json”</font> and not contains “<font face="Courier New">text/html</font>” a <font face="Courier New">JsonResult</font> should be returned</p>
<p>- Contains “<font face="Courier New">text/xml</font>” and not contains “<font face="Courier New">text/html</font>” a <font face="Courier New">XmlResult</font> should be returned</p>
<p>If the requested content type can not be handled by none of the previous statements, a response with a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html" target="_blank">HTTP Status Code 406 – Not Acceptable</a> should be returned.</p>
<p>For this post. I will start with the same controller class that I used in the previous one:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class ClientController : Controller
    {
        public ActionResult Index()
        {
            var clients = new[] {
            new Client {FirstName = &quot;John&quot;, LastName = &quot;Smith&quot;},
            new Client {FirstName = &quot;Dave&quot;, LastName = &quot;Boo&quot;},
            new Client {FirstName = &quot;Garry&quot;, LastName = &quot;Foo&quot;}
                               };

            return View(clients);
        }

    }

    public class Client
    {
        public string FirstName{get;set;}

        public string LastName{get; set; }

    }</pre>
<p>&#160;</p>
<p>In order to be able to format the result based on the requested content-type on the HTTP header, I will create a base controller class that will provide this functionality to the controller. I will call it <font face="Courier New">ContentTypeAwareController</font>.</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class ContentTypeAwareController : Controller
{
   public virtual IContentTypeHandlerRepository HandlerRepository { get; set; } 

    protected ActionResult ResultWith(object model)
        {
            var handler = HandlerRepository.GetHandlerFor(HttpContext);
            return handler.ResultWith(model);
        }
    }</pre>
<p>&#160;</p>
<p>That’s it. This base class is responsible just to ask the Handler Repository for the right handler to the given HttpContext and call the ResultWith() method on the returned handler.</p>
<p>The IContentTypeHandler interface is pretty simple as well:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public interface IContentTypeHandler
{
    bool CanHandle(HttpContextBase context);
    ActionResult ResultWith(object model);
}</pre>
<p>&#160;</p>
<p>Simple and intuitive, right?</p>
<p>Let’s implement this interface then, but first let’s set the expectations as unit tests:</p>
<p>&#160;</p>
<pre class="brush: csharp;">[TestFixture]
    public class JsonHandlerTest : HandlerTestBase
    {
        [Test]
        public void should_return_a_JsonResult()
        {
            var handler = new JsonHandler();
            var result = handler.ResultWith(&quot;whatever&quot;);
            result.ShouldBeType&lt;JsonResult&gt;();
        } 

        [Test]
        public void should_Handle_request_when_content_type_requested_contains_Json()
        {
            Headers.Add(&quot;Accept&quot;, &quot;application/json&quot;); 

            var handler = new JsonHandler();
            handler.CanHandle(HttpContext).ShouldBeTrue();
        } 

        [Test]
        public void should_not_handle_request_when_content_type_requested_does_not_contain_json()
        {
            Headers.Add(&quot;Accept&quot;, &quot;text/xml&quot;); 

            var handler = new JsonHandler();
            handler.CanHandle(HttpContext).ShouldBeFalse();
        }
    }</pre>
<p>&#160;</p>
<p>To keep the post short, I will put here just the test above, all the other tests are in the solution on <a href="http://github.com/pedroreys/BlogPosts" target="_blank">github</a>. </p>
<p>The implementation of the <font face="Courier New">JsonHandler</font> is below:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class JsonHandler : IContentTypeHandler
    {
        public const string _acceptedType = &quot;application/json&quot;;
        public bool CanHandle(HttpContextBase context)
        {
            var acceptHeader = context.Request.Headers.Get(&quot;Accept&quot;); 

            return acceptHeader.Contains(_acceptedType);
        } 

        public ActionResult ResultWith(object model)
        {
            return new JsonResult
                       {
                           Data = model,
                           ContentEncoding = null,
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet
                       };
        }</pre>
<p>&#160;</p>
<p>It’s important to set the value for the <font face="Courier New">JsonRequestBehavior</font> property on the <font face="Courier New">JsonResult</font> object. Otherwise you will end-up with a <font face="Courier New">InvalidOperationException</font>.</p>
<p>The other handlers are pretty straight-forward as well.</p>
<p>The one to handle requests for Xml:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class XmlHandler : IContentTypeHandler
{
    public const string _acceptedType = &quot;text/xml&quot;;

    public bool CanHandle(HttpContextBase context)
    {
        var acceptHeader = context.Request.Headers.Get(&quot;Accept&quot;);

        return acceptHeader.Contains(_acceptedType);
    }

    public ActionResult ResultWith(object model)
    {
        return new XmlResult(model);
    }
}</pre>
<p>&#160;</p>
<p>And the other to be the default, Html handler:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class HtmlHandler : IContentTypeHandler
{
    public const string _acceptedType = &quot;text/html&quot;;

    public bool CanHandle(HttpContextBase context)
    {
        var acceptHeader = context.Request.Headers.Get(&quot;Accept&quot;);

        return acceptHeader.Contains(_acceptedType);

    }

    public ActionResult ResultWith(object model)
    {
        return new ViewResult
                   {
                       ViewData = new ViewDataDictionary(model),
                   };
    }
}</pre>
<p>&#160;</p>
<p>&#160;</p>
<p>And finally, we will have a handler to return the 406 code in case of the others handlers not being able to handle the requested content type.</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class NotAcceptedContentTypeHandler : IContentTypeHandler
{
    public bool CanHandle(HttpContextBase context)
    {
        return true;
    }

    public ActionResult ResultWith(object model)
    {
        return new NotAcceptedContentTypeResult();
    }
}</pre>
<p>&#160;</p>
<p>With all that code in place, all we have left to do is to make the <font face="Courier New">ClientController</font> to inherit from the <font face="Courier New">ContentTypeAwareController</font> and call the <font face="Courier New">ResultWith()</font> method:</p>
<p>&#160;</p>
<pre class="brush: csharp;">public class ClientController : ContentTypeAwareController
{
    public ActionResult Index()
    {
        var clients = new[]{
            new Client {FirstName = &quot;John&quot;, LastName = &quot;Smith&quot;},
            new Client {FirstName = &quot;Dave&quot;, LastName = &quot;Boo&quot;},
            new Client {FirstName = &quot;Garry&quot;, LastName = &quot;Foo&quot;}
                           };

            return ResultWith(clients);
        }

    }</pre>
<p>
  </p>
<p>That’s it. The Client Controller now is able to respond to Json, Xml or Html requests. Let’s check it.</p>
<p>The web page is still being rendered as expected. Fine.</p>
<p>&#160;</p>
<p><a title="html" href="http://www.flickr.com/photos/22313104@N04/4594093858/"><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="html" src="http://farm5.static.flickr.com/4043/4594093858_af5b693db0.jpg" /></a></p>
<p>&#160;</p>
<p>But now, let’s see what responses do I get when I change the Http Header to “<font face="Courier New">application/json</font>”:</p>
<p>&#160;</p>
<p><a title="json" href="http://www.flickr.com/photos/22313104@N04/4594220022/"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" border="0" alt="json" src="http://farm5.static.flickr.com/4061/4594220022_321ba545c1.jpg" /></a></p>
<p>&#160;</p>
<p>Yeah,&#160; a Json result. Cool. What about “<font face="Courier New">text/xml</font>”:</p>
<p>&#160;</p>
<p><a title="xml" href="http://www.flickr.com/photos/22313104@N04/4593603183/"><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="xml" src="http://farm4.static.flickr.com/3391/4593603183_2b80e4c978.jpg" /></a></p>
<p>&#160;</p>
<p>Yeap, that works too. Finally, let’s see if the 406 status code is returned when an invalid content type is requested:</p>
<p>&#160;</p>
<p><a title="406" href="http://www.flickr.com/photos/22313104@N04/4594219796/"><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="406" src="http://farm2.static.flickr.com/1136/4594219796_7606432360.jpg" /></a></p>
</p>
<p>&#160;</p>
<p>So, with not so much code the Client Controller now is able to format its result based on the Content Type requested on the HTTP Header, as it should have been before. Off course this is a spike and the code can be improved. Feel free to grab it from <a href="http://github.com/pedroreys/BlogPosts" target="_blank">github</a> and improve it. </p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/EAMscLIz6Q0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2010/05/10/handling-content-type-as-we-should-through-http-headers/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2010/05/10/handling-content-type-as-we-should-through-http-headers/</feedburner:origLink></item>
		<item>
		<title>Mimicking Rails formatter behavior in ASP.NET MVC</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/rlxvgxt4fWs/</link>
		<comments>http://pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 18:53:08 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Routes]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://blog.pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/</guid>
		<description><![CDATA[I was reading this (pt-BR) thread at the brazilian .Net mailing list &#8211; dotNetArchitects – which, at first, did not have nothing to do with Rails nor output format. But, as usual, the thread deviated from the initial subject – &#8230;<p class="read-more"><a href="http://pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>I was reading <a href="http://groups.google.com/group/dotnetarchitects/browse_thread/thread/036023bee2897584?hl=pt#">this (pt-BR) thread</a> at the brazilian .Net mailing list &#8211; <a href="http://www.dotnetarchitects.net/">dotNetArchitects</a> – which, at first, did not have nothing to do with Rails nor output format. But, as usual, the thread deviated from the initial subject – what is not a bad thing &#8211; and somehow got into the fact that it would be nice to have in ASP.NET, more specifically in <a href="http://www.asp.net/mvc/">ASP.NET MVC</a>, a behavior similar to what Rails have by default to handle output formatters.</p>
<p>In Rails is possible to handle the format that will be returned by the controller as in the following example:</p>
<pre class="brush: ruby;">class PeopleController &lt; ApplicationController

def index 

@people = People.find(:all)

respond_to do |format|

format.html

format.json(render :json =&gt; @people.to_json)

format.xml(render :xml =&gt; @people.to_xml)

end

end</pre>
<p>With the controller above, if&#160; one requests the url <font face="Courier New">/people/index</font> the result will be in <font face="Courier New">html</font>. but, if <font face="Courier New">people/index.json</font> is requested instead, the result will be a <font face="Courier New">json</font> file.</p>
<p>That’s a great feature when one is developing an API and let the client code to decide the format it wants to receive the data. Unfortunately, we can’t do that out of the box with ASP.NET MVC. But, ASP.NET MVC gives us lots of extensions points and that allows us to quite easily implement the functionality to mimic this neat behavior. </p>
<p><em>First, a disclaimer. The solution that I will present is heavily based on the solution present in the routing chapter of the book <a href="http://www.amazon.com/gp/product/1933988622?ie=UTF8&amp;tag=pedroreys-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1933988622">ASP.NET MVC in Action</a>. The new edition of the book, now covering MVC 2, is, by the time I write this post, in public review. You can get more information about it on this </em><a href="http://jeffreypalermo.com/blog/mvc-2-in-action-book-conducting-public-reviews/"><em>post</em></a><em> from Jeffrey Palermo. If you are an ASP.NET developer and don’t have read the book yet, stop everything you are doing and <a href="http://www.amazon.com/gp/product/1933988622?ie=UTF8&amp;tag=pedroreys-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1933988622">go buy it now</a>.</em></p>
<p>All that said, lets have some fun.</p>
<p>In our application we have this simple Person entity:</p>
<pre class="brush: csharp;">public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}</pre>
<p>&#160;</p>
<p>The application itself is really simple, it just shows a list of People. And yes, I was lazy and used the MVC sample.</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_1" src="http://static.flickr.com/4012/4334558401_cdf8faffec.jpg" />&#160;</p>
<p>I will omit the view code for the sake of brevity as it has nothing to do with the goal of this post.</p>
<p>The <font face="Courier New">PeopleController</font> is pretty dumb too, it just returns a collection of <font face="Courier New">Person</font> to the View: </p>
<pre class="brush: csharp;">public class PeopleController : Controller
{
    public ActionResult Index()
    {
        var people = new[]
                {
                    new Person{FirstName = &quot;Joao&quot;, LastName = &quot;Silva&quot;},
                    new Person{FirstName = &quot;John&quot;, LastName = &quot;Doe&quot;},
                    new Person{FirstName = &quot;Jane&quot;, LastName = &quot;Smith&quot;}
                 };
        return View(people);
    }
}</pre>
<p>So, it works, pretty straight-forward with default routing. Now, we want to mimic the Rails formatter behavior. So, what we want is that the url <font face="Courier New">/People/Index.json</font> returns a <font face="Courier New">json</font> file instead of the html page. Ok, what we first need to do is check to see if this new url will be routed to the correct Action with the actual route configuration. </p>
<p>With the help of <a href="http://www.codeplex.com/MVCContrib">MvcContrib</a> project, we can write the following test to check if our route works as we expect:</p>
<pre class="brush: csharp;">[TestFixtureSetUp]
public void Setup()
{
    MvcApplication.RegisterRoutes(RouteTable.Routes);
}

[Test]
public void Should_map_People_url_to_people_with_default_action()
{
    &quot;~/people&quot;.Route().ShouldMapTo&lt;PeopleController&gt;(x =&gt; x.Index());
}

[Test]
public void Should_map_People_index_json_url_to_people_matching_index_action()
{
    &quot;~/people/index.json&quot;.Route().ShouldMapTo&lt;PeopleController&gt;(x =&gt; x.Index());
}</pre>
<p>As expected, the former test passes, but the latter, the one that tests the new behavior we want to test don’t. And more important, it fails as we expected it to fail.</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_2" src="http://static.flickr.com/4003/4335338096_9f9e265960.jpg" /></p>
</p>
<p>In order to make it work, we need to add a new route to our Route Dictionary.</p>
<pre class="brush: csharp;">routes.MapRoute(
&quot;Format&quot;,
&quot;{controller}/{action}.{format}/{id}&quot;,
new {id = &quot;&quot;});</pre>
<p>With this new route defined, we now get a green test. Neat.</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_3" src="http://static.flickr.com/2769/4335379468_b6e8aae0dc.jpg" /></p>
</p>
<p>With the route working and the request being routed to the right method, the controller now needs to extract the format information from the route data and handle the output format accordingly.&#160; To achieve this, I’ll create a <a href="http://martinfowler.com/eaaCatalog/layerSupertype.html">Layer SuperType</a>, a abstract class that will derive from the base <font face="Courier New">Controller</font> class. The <font face="Courier New">PeopleController</font>, then, will derive from this new class instead of the base <font face="Courier New">Controller</font> one.</p>
<p>This new Controller class, that I will name <font face="Courier New">RailsWannabeController</font>, will override the <font face="Courier New">OnActionExecuting</font> method of the Controller base class in order to extract the requested format from the <font face="Courier New">RouteData</font>. It also will have a property named <font face="Courier New">Format</font> who will store the format information. Finally, it will have a <font face="Courier New">FormatResult</font> method that returns the right <font face="Courier New">ActionResult</font> accordingly to the requested format.</p>
<p>Here is the test to ensure that <font face="Courier New">RailsWannabeController</font> correctly extracts the format information out of the <font face="Courier New">RouteData</font>.</p>
<pre class="brush: csharp;">[Test]
public void Should_extract_format_information_from_RouteData()
{
    var expectedFormat = &quot;json&quot;;
    var routeData = Stub&lt;RouteData&gt;();
    routeData.Values.Add(&quot;format&quot;,expectedFormat);

    var filterContext =
        new ActionExecutingContext()
        {
            Controller = Stub&lt;RailsWannabeController&gt;(),
            RouteData = routeData
         };

    var controller = new StubController();
    controller.ActionExecuting(filterContext);
    var requestedFormat = controller.RequestedFormat;
    Assert.AreEqual(expectedFormat,requestedFormat);
}</pre>
<p>As the <font face="Courier New">RailsWannabeController</font> will be a abstract class, a <font face="Courier New"><strike>MockController</strike> StubController</font> concrete class has to be created. This class will derive from <font face="Courier New">RailsWannabeController</font> and will have a public method to enable the <font face="Courier New">OnActionExecuting</font> method to be called. It also will have a <font face="Courier New">RequestedFormat</font> property to expose the value of the requested format extracted from the <font face="Courier New">RouteData</font>.</p>
<pre class="brush: csharp;">public class StubController : RailsWannabeController
{
    public string RequestedFormat { get { return base.Format; } }

    public void ActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }
}</pre>
</p>
<p><font face="Courier New">Now, all we need to do to make this test pass is code the RailsWannabeController class. </font></p>
<pre class="brush: csharp;">public class RailsWannabeController : Controller
{
    protected static string[]  ValidFormats = new [] {&quot;html&quot;,&quot;json&quot;,&quot;xml&quot;};
    protected string Format { get; set; }

    private const string formatKey = &quot;format&quot;;

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        ExtractRequestedFormat(filterContext.RouteData.Values);
    }

    private void ExtractRequestedFormat(RouteValueDictionary routeValues)
    {
        if(routeValues.ContainsKey(formatKey))
        {
            var requestedFormat = routeValues[formatKey].ToString().ToLower();
            if(ValidFormats.Contains(requestedFormat))
            {
                Format = requestedFormat;
                return;
            }
        }
        Format = &quot;html&quot;;
    }
}</pre>
<p>Now that we got a green bar, we have to test if the <font face="Courier New">ActionResult</font> returned by the <font face="Courier New">FormatResult</font> method is from the type requested. That means that if the “<font face="Courier New">json</font>” format is passed in the <font face="Courier New">RouteData</font>, the <font face="Courier New">FomatResult</font> method the object returned must be of type <font face="Courier New">JsonResult. </font></p>
<pre class="brush: csharp;">public void Should_return_the_correct_Action_Result()
{
    var expectedFormat = &quot;json&quot;;
    var routeData = Stub&lt;RouteData&gt;();
    routeData.Values.Add(&quot;format&quot;, expectedFormat);

    var filterContext = new ActionExecutingContext()
    {
        Controller = Stub&lt;RailsWannabeController&gt;(),
        RouteData = routeData
    };

    var controller = new StubController();
    controller.ActionExecuting(filterContext);

    var people = new[]{
                         new Person{FirstName = &quot;Joao&quot;, LastName = &quot;Silva&quot;},
                         new Person{FirstName = &quot;John&quot;, LastName = &quot;Doe&quot;},
                         new Person{FirstName = &quot;Jane&quot;, LastName = &quot;Smith&quot;}
                     };

    var formattedResult = controller.GetFormattedResult(people);
    Assert.AreEqual(typeof(JsonResult),formattedResult.GetType());
}</pre>
<p>&#160;</p>
<p>There is a LOT of code in this test. Much more then I’d like it to have. But to keep the code as explicit as possible, for sake of clarity, I left it that way. I’ll let the refactoring of this code as an exercise for the reader.</p>
<p>As you may guess from the code above, the <font face="Courier New"><strike>MockController</strike> StubController</font> class had to be modified to include the <font face="Courier New">GetFormattedResult</font> method.</p>
<pre class="brush: csharp;">public class StubController : RailsWannabeController
{
    public string RequestedFormat { get { return base.Format; } }

    public void ActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }

    public ActionResult GetFormattedResult(object model)
    {
        return base.FormatResult(model);
    }
}</pre>
<p>&#160;</p>
<p>In the&#160; <font face="Courier New">RailsWannabeController</font> we have to create a <font face="Courier New">FormatResult</font> method that, as it name states, format the result accordingly to the format requested.</p>
<pre class="brush: csharp;">protected ActionResult FormatResult(object model)
{
    switch (Format)
    {
        case &quot;html&quot;:
            return View(model);
        case &quot;json&quot;:
            return Json(model);
        case &quot;xml&quot;:
            return new XmlResult(model);
        default:
            throw new FormatException(
                string.Format(&quot;The format \&quot;{0}\&quot; is invalid&quot;, Format));
    }
}</pre>
<p>ASP.NET MVC framework gives us the <font face="Courier New">Json</font> method out of the box. The <font face="Courier New">XmlResult</font> is provided by the MvcContrib project.</p>
<p>Now, all we have to do is change the <font face="Courier New">PeopleController</font> class to derive from the Layer SuperType instead of the Controller base class. And change the <font face="Courier New">View()</font> method call to be a call to the <font face="Courier New">FormatResult</font> method.</p>
<pre class="brush: csharp;">public class PeopleController : RailsWannabeController
{
    public ActionResult Index()
    {
        var people = new[]
            {
                new Person{FirstName = &quot;Joao&quot;, LastName = &quot;Silva&quot;},
                new Person{FirstName = &quot;John&quot;, LastName = &quot;Doe&quot;},
                new Person{FirstName = &quot;Jane&quot;, LastName = &quot;Smith&quot;}
             };
        return FormatResult(people);
    }
}</pre>
<p>OK, all the tests are green and we are done coding. Let’s check if all we’ve done works properly.</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_4" src="http://static.flickr.com/4068/4337240149_0c587a80fd.jpg" /></p>
<p>Using the default route we get the same result. Great. </p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_6" src="http://static.flickr.com/4070/4337983998_793d67231f.jpg" /></p>
<p>If “json” format is provided in the URL we get a <font face="Courier New">json</font> file instead. Woot.</p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" border="0" alt="Rails_MVC_7" src="http://static.flickr.com/4011/4337240393_cf05be4942.jpg" /></p>
<p>Finally, requesting a xml we get the result in a XML file. That’s it we are done.</p>
<p>I know the post is a little bit long, but that’s because my intention was to explicit all the process of mimicking the behavior of the Rails formatter. And, as you should do as well, I managed to have the code I was working on to be covered by tests that gave me the confidence that I wasn’t breaking anything while I was making the changes. It is specially important to cover your routes with tests as route changes can introduce some hard to find bugs. I hope this post helps to show that, although ASP.NET MVC may not have all the features we want it to have, it’s high extensibility allows us to extend it and easily introduce new behaviors.</p>
<p>As I’m not a native English speaker, I ask and encourage you to point out not only technical mistakes but also any language related mistakes that I’ve made at this post. </p>
<p><strong>UPDATE:</strong> As Giovanni correctly pointed out in his comment, the <font face="Courier New">MockController</font> class is not a Mock but a Stub. I renamed the class to <font face="Courier New">StubController</font> to avoid misunderstandings. Thanks, Giovanni. </p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/rlxvgxt4fWs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2010/02/07/mimicking-rails-formatter-behavior-in-asp-net-mvc/</feedburner:origLink></item>
		<item>
		<title>Alternative MBA with Seth Godin</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/1vSP42ziWIs/</link>
		<comments>http://pedroreys.com/2008/12/03/alternative-mba-with-seth-godin/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 20:24:23 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Recomendations]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[coach]]></category>
		<category><![CDATA[internship]]></category>
		<category><![CDATA[marketing]]></category>
		<category><![CDATA[opportunity]]></category>

		<guid isPermaLink="false">http://blog.pedroreys.com/?p=25</guid>
		<description><![CDATA[Look this trade-off: Instead of getting a MBA, spend 6 months at the office of one of the greatest marketing authors and blogger. That&#8217;s what Seth Godin is offering. Quoting him, what he offers is: Six intense months working with &#8230;<p class="read-more"><a href="http://pedroreys.com/2008/12/03/alternative-mba-with-seth-godin/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Look this trade-off: Instead of getting a MBA, spend 6 months at the office of one of the greatest marketing authors and blogger.</p>
<p>That&#8217;s what <a href="http://sethgodin.typepad.com/" target="_blank">Seth Godin</a> is <a href="http://www.squidoo.com/Alternative-MBA" target="_blank">offering</a>. Quoting him, what he offers is:</p>
<blockquote><p>Six intense months working with a few other amazing people (and me.)</p></blockquote>
<p>It is a really awesome opportunity for one who already lives or can afford the expenses of living 6 months in NYC.</p>
<p>It is not everyday that one <span style="text-decoration: line-through;">have</span> has the chance to get 6 months of coaching and learning from someone like Seth, and for <strong>free</strong>.</p>
<p>Source: <a href="http://www.squidoo.com/Alternative-MBA" target="_blank">Squiido</a> via <a href="http://scrum4you.wordpress.com/2008/12/02/seth-godin-offers-you-a-huge-opportunity-go-for-it/" target="_blank">Scrum4You</a></p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/1vSP42ziWIs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2008/12/03/alternative-mba-with-seth-godin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2008/12/03/alternative-mba-with-seth-godin/</feedburner:origLink></item>
		<item>
		<title>Hi!</title>
		<link>http://feedproxy.google.com/~r/pedroreys/~3/N0UD3D7t5aA/</link>
		<comments>http://pedroreys.com/2008/11/03/hi/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 17:37:00 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Hello World]]></category>

		<guid isPermaLink="false">http://pedroreys.com/blog/?p=7</guid>
		<description><![CDATA[Hi everybody. This is the first post of my new blog. Some of you may be familiar with the Portuguese written blog that I co-author with Jorge Maia. At this one I&#8217;ll be writing in English only, I hope. :) &#8230;<p class="read-more"><a href="http://pedroreys.com/2008/11/03/hi/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Hi everybody.</p>
<p>This is the first post of my new blog.</p>
<p>Some of you may be familiar with the Portuguese written <a href="http://www.gerenciamentoagil.com.br" target="_blank">blog</a> that I co-author with Jorge Maia. At this one I&#8217;ll be writing in English only, I hope. :)</p>
<p>Well, as soon as I finish all the WordPress settings, I will start to post here.</p>
<p>For you who don&#8217;t know me yet, I suggest reading the &#8220;<a href="http://blog.pedroreys.com/?page_id=2" target="_blank">About</a>&#8221; section.</p>
<p>Cheers,</p>
<p>Pedro Reys</p>
<img src="http://feeds.feedburner.com/~r/pedroreys/~4/N0UD3D7t5aA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://pedroreys.com/2008/11/03/hi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://pedroreys.com/2008/11/03/hi/</feedburner:origLink></item>
	</channel>
</rss>

