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

<channel>
	<title>{ Code: Impossible } &#187; asp.net</title>
	<atom:link href="http://codeimpossible.com/tag/asp-net/feed/" rel="self" type="application/rss+xml" />
	<link>http://codeimpossible.com</link>
	<description>this = HowI.Roll();</description>
	<lastBuildDate>Thu, 29 Jul 2010 02:58:45 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Migrating Asp.net MVC Projects from MVC 1.0 to 2.0</title>
		<link>http://codeimpossible.com/2010/04/06/migrating-asp-net-mvc-projects-from-mvc-1-0-to-2-0/</link>
		<comments>http://codeimpossible.com/2010/04/06/migrating-asp-net-mvc-projects-from-mvc-1-0-to-2-0/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 06:35:35 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=837</guid>
		<description><![CDATA[The Asp.net Mvc 2.0 RTM came out last month and a lot of people are converting their projects over. If you&#8217;re just starting to manually move your projects over then stop what you are doing, download and run the Mvc Converter. It will save you eons of time and frustration.
If you are like me, however, [...]]]></description>
			<content:encoded><![CDATA[<p>The<a href="http://haacked.com/archive/2010/03/11/aspnet-mvc2-released.aspx" target="_blank"> Asp.net Mvc 2.0 RTM came out last month</a> and a lot of people are converting their projects over. If you&#8217;re just starting to manually move your projects over then stop what you are doing, <a href="http://weblogs.asp.net/leftslipper/archive/2010/03/10/migrating-asp-net-mvc-1-0-applications-to-asp-net-mvc-2-rtm.aspx" target="_blank">download and run the Mvc Converter</a>. It will save you eons of time and frustration.</p>
<p>If you are like me, however, and started porting your project over manually and are now knee deep in WTFBBQ sauce then follow the steps below and your project should be up and running in no time.</p>
<p>1. Back up your project. Just in case.</p>
<p>2. Open your project file(s) inside your favorite text editor (one with a decent find/replace system). Open the Find &amp; Replace dialog and find <code>"603c0e0b-db56-11dc-be95-000d561079b0"</code>, replacing it with <code>"F85E285D-A4E0-4152-9332-AB1D724D3325"</code>. My project turned up 1 result.</p>
<p>3. Open the Web.Config files in the root of the project and the root of the /Views folder. Open the Find &amp; Replace dialog again, this time searching for <code>"System.Web.Mvc, Version=1.0.0.0"</code> and replacing it with <code>"System.Web.Mvc, Version=2.0.0.0"</code>.</p>
<p>4. Add the following BindingRedirect to the bottom of the root Web.Config, just before the &lt;/Configuration&gt; node.</p>
<pre class="prettyprint"><code>
&lt;runtime&gt;
  &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
    &lt;dependentAssembly&gt;
      &lt;assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/&gt;
      &lt;bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/&gt;
    &lt;/dependentAssembly&gt;
  &lt;/assemblyBinding&gt;
&lt;/runtime&gt;
</code></pre>
<p>5. Open the solution in Visual Studio and replace the references to System.Web.Mvc 1.0 with the 2.0 assembly.<br />
6. Finally, and only if you really need them, open a new MVC 2.0 project and copy all the files in the /Scripts folder to your project. </p>
<p>Enjoy your freshly migrated project!</p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2010/04/06/migrating-asp-net-mvc-projects-from-mvc-1-0-to-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tracking .Net Service Requests in Fiddler</title>
		<link>http://codeimpossible.com/2009/08/17/tracking-net-service-requests-in-fiddler/</link>
		<comments>http://codeimpossible.com/2009/08/17/tracking-net-service-requests-in-fiddler/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 18:52:59 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[asp.]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=620</guid>
		<description><![CDATA[Earlier today I had to debug a function in our code that was calling an external webservice at a clients&#8217; site. The webservice returns a list of items and the code on our end is supposed to place them in ascending order based on each items Order property.
The client pointed that the our order wasn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier today I had to debug a function in our code that was calling an external webservice at a clients&#8217; site. The webservice returns a list of items and the code on our end is supposed to place them in ascending order based on each items Order property.</p>
<p>The client pointed that the our order wasn&#8217;t matching up with what they were seeing internally so I spoke with their developer who suggested that we make sure that the request wasn&#8217;t being cached on my machine.</p>
<p>I opened up Fiddler locally and was surprised to see that the none of the request/response data for the connection to the webservice was showing up. </p>
<p>Fiddler, for those that don&#8217;t know is a really excellent Http tracing application that allows you to see what kind of http traffic is going in and out over your network connection. You can <a href="http://www.fiddler2.com/fiddler2/">download fiddler here</a>.</p>
<p>Thankfully, Fiddler runs a simple proxy service which you can point your service requests to in .net using:</p>
<pre class="prettyprint"><code>
if (System.Environment.MachineName.ToLower().Equals("MyMachineName"))
{
    service.Proxy = new System.Net.WebProxy("http://localhost:8888");
}
</code></pre>
<p>After adding that code we were off and debugging our .Net service requests in Fiddler!</p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2009/08/17/tracking-net-service-requests-in-fiddler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>W.O.M.M. #4 &#8211; Asp MVC Route Attributes</title>
		<link>http://codeimpossible.com/2009/06/22/w-o-m-m-4-asp-mvc-route-attributes/</link>
		<comments>http://codeimpossible.com/2009/06/22/w-o-m-m-4-asp-mvc-route-attributes/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 06:40:39 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=403</guid>
		<description><![CDATA[Download the source code mentioned in this blog post.

A few weeks ago on the StackOverflow podcast, something Jeff said got me thinking. Jeff was discussing how the stackoverflow team implemented their route mappings:

Those routes are&#8230; the way we implemented them are actually like decorators. Attributes on the methods. - Jeff Atwood (stackoverflow episode #54)

This instantly [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.box.net/shared/1q4bq5scuz" target="_blank">Download the source code mentioned in this blog post.</a></p>
<p><img class="alignleft" title="works-on-my-machine-starburst" src="http://wpup.codeimpossible.com/2009/06/works-on-my-machine-starburst.jpg" alt="works-on-my-machine-starburst" /></p>
<p>A few weeks ago <a href="http://itc.conversationsnetwork.org/audio/download/ITC.SO-Episode54-2009.05.20.mp3">on the StackOverflow podcast</a>, something Jeff said got me thinking. Jeff was discussing how the stackoverflow team implemented their route mappings:</p>
<p><em><br />
Those routes are&#8230; the way we implemented them are actually like decorators. Attributes on the methods. <cite>- Jeff Atwood (stackoverflow episode #54)</cite><br />
</em></p>
<p>This instantly piqued my interest and I completely zoned out for the rest of the podcast: caught up in working out the details of how I could do this for my own Asp.net MVC projects. </p>
<p>Coming up with the actual attribute code was easy; writing the code to set up all the Routes using only data defined in by the attribute was tricky.</p>
<p>Being new to attributes, and reflection in general, it took me a few hours until I had a very basic demo working. However, I was really starting to like where it was going.</p>
<p class="right side-note callout-green">
As a side note: There are lot of &#8220;helper&#8221; classes and objects in the route attribute project (it feels cluttered to me) and the reason I did this was to make the code in AssemblyExtensions.GetRoutes() easier to read.
</p>
<p>After a few nights of <a href="http://twitter.com/digitalBush/status/2121662803" target="_blank">Mtn Dew and convenience-store cherry-pie</a> I finished the rough code, tests and demo project (included in this blog post) and I was starting to realize that:</p>
<ol>
<li>Using the attributes is more declaritive and it feels cleaner</li>
<li>Having your route information right above your actions is incredibly useful</li>
<li>I had no more need to switch back and forth between your controller and the Global.asax.cs</li>
</ol>
<h2>How does it work?</h2>
<p>All of the real work for the RouteAttribute is done in the AssemblyExtensions class. This class uses extension methods to augment the System.Reflection.Assembly class with two methods: GetControllers() and GetRoutes().</p>
<p>GetRoutes is the only method that is used by other classes, I made GetControllers public for unit testing.</p>
<h3>GetRoutes()</h3>
<p>GetRoutes&#8217; first order of business is to make a list of data that it will need to build out all the routes for the assembly it was passed. After thats done GetRoutes will loop through the collected route data, build up each route and add it to the dictionary that will eventually be returned.</p>
<pre class="prettyprint"><code>
namespace CodeImpossible.Mvc.Routing
{
    public static class AssemblyExtensions
    {

        public static BindingFlags ActionFlags =
            BindingFlags.Instance |
            BindingFlags.Public |
            BindingFlags.DeclaredOnly;

        public static IList&lt;ControllerMetaData&gt; GetControllers(this Assembly assembly)
        {
            var controllers = assembly.GetTypes().ToList().FindAll(type =>
            {
                var isValidController = type.IsClass &#038;&#038;
                    type.IsPublic &#038;&#038;
                    type.IsSubclassOf&lt;Controller&gt;();

                var hasValidActions = type.GetMethods(ActionFlags).ToList().Any(m =>
                {
                    var valid = false;
                    if (m.ReturnParameter != null &#038;&#038; m.ReturnParameter.ParameterType == typeof(ActionResult))
                    {
                        valid = m.GetAttributesOfType&lt;RouteAttribute&gt;().Count > 0;
                    }

                    return valid;
                });

                return isValidController &#038;&#038; hasValidActions;
            }).Select&lt;Type, ControllerMetaData&gt;((t) => new ControllerMetaData(t)).ToList();

            return controllers;
        }

        public static IDictionary&lt;string, Route&gt; GetRoutes(this Assembly assembly)
        {
            var Routes      = new Dictionary&lt;string, Route&gt;();

            var data = (from c in assembly.GetControllers()
                        from a in c.GetActions()
                        from r in a.Data
                        select new
                        {
                            ControllerName = c.Name,
                            ActionName = a.Name,
                            RouteData = r,
                            RouteParams = a.Params
                        }).ToList();

            foreach (var r in data)
            {
                var route               = new Route(r.RouteData.RoutePath, new MvcRouteHandler());
                route.Constraints       = new RouteValueDictionary();
                route.Defaults          = new RouteValueDictionary(new {
                    controller = r.ControllerName,
                    action = r.ActionName
                });

                if (r.RouteData.RequireRouteParams &#038;&#038; r.RouteParams.Count() == 0)
                {
                    throw new MissingRouteParameterException("Unknown", r.RouteData.RoutePath);
                }

                var missingParams = new List&lt;ParameterMetaData&gt;();

                if (r.RouteData.RequireRouteParams)
                {
                    missingParams = (from p in r.RouteParams
                                     where r.RouteData.RoutePath.IndexOf("{" + p.Name + "}") == -1
                                     select p).ToList();
                }

                if (missingParams.Count > 0)
                {
                    var param = missingParams.First();
                    throw new MissingRouteParameterException(param.Name, r.RouteData.RoutePath);
                }

                foreach (var param in r.RouteParams)
                {
                    if (param.Data != null)
                    {
                        if (param.Data.DefaultValue != null)
                        {
                            route.Defaults.Add(param.Name, param.Data.DefaultValue);
                        }

                        if (param.Data.Constraint != null)
                        {
                            route.Constraints.Add(param.Name, param.Data.Constraint);
                        }
                    }
                }

                Routes.Add(r.RouteData.Name ?? r.RouteData.RoutePath, route);
            }

            return Routes;
        }
    }
}
</code></pre>
<h2>Getting the Routes into the RouteTable</h2>
<p>Slapping route attributes onto your classes and methods is all well and good but it doesn&#8217;t mean anything unless we can get those routes into the RouteTable object easliy. Originally I had the code to add the routes looking something like</p>
<pre class="prettyprint"><code>
var routes = Assembly.GetCurrentExecutingAssembly().GetRoutes();

routes.ForEach(r => RouteTable.Add(r));
</code></pre>
<p>This, although pretty easy, wasn&#8217;t as readible as I wanted. So I added some extension methods to the RouteTable class:</p>
<pre class="prettyprint"><code>
RouteTable.Routes.IncludeRoutesFromAssembly();
</code></pre>
<p>I think both of these are much clearer than doing:</p>
<pre class="prettyprint"><code>
RouteTable.Routes.MapRoute("Root",
    "",
    new { controller = "Test", action = "GetItem", id = 1 });

RouteTable.Routes.MapRoute("Search",
    "Search/{id}",
    new { controller = "Test", action = "Search", id = 1 });
//.. SNIP ...
</code></pre>
<h2>Using the RouteAttribute and RouteParamAttribute</h2>
<p>In the controller &#8220;TestController&#8221; below there are three actions: Index, FindByText, and GetItem. Using the RouteAttribute and RouteParamAttribute makes it pretty clear that the routes for FindByText and GetItem are the same but use different RouteContraints. </p>
<p>So a request for /Test/Search/Hello will go to FindByText while /Test/Search/1 will go to GetItem. Also notice how GetItem has a default value of 2 for the id argument.</p>
<pre class="prettyprint"><code>
public class TestController : Controller
{

    [Route(RoutePath = "Test")]
    public ActionResult Index()
    {

        return View();
    }

    [Route(RoutePath = "Test/Search/{query}")]
    public ActionResult FindByText(
        [RouteParam(Constraint="[a-zA-Z]{1,}")]
        string query)
    {

        return View();
    }

    [Route(RoutePath = "Test/Search/{id}")]
    public virtual ActionResult GetItem(
        [RouteParam(Constraint=@"\d{1,}", DefaultValue=2)]
        int id)
    {

        return View();
    }
}</code></pre>
<p>There is support for binding multiple routes to the same action; just add another Route attribute:</p>
<pre class="prettyprint"><code>
[Route("Products/Search/{id}")]
[Route("Products/{id}")]
public ActionResult GetProductById(int id)
{
    return View();
}
</code></pre>
<h2>Downsides or things I haven&#8217;t gotten to yet</h2>
<p>Just some gotchas that I think people might raise issue with.</p>
<p><strong>All of your controllers must inherit from the System.Web.Mvc.Controller class</strong><br />
This isn&#8217;t really a big deal because if you are using Asp.net MVC then you really should inherit from the Controller class, but for those of you using FubuMVC or another MVC framework this should be easy to change.</p>
<p><strong>Attributes can be ugly</strong><br />
I know a few people out there are against attributes but I think that this is a more than acceptable use because it made the code much easier to understand.</p>
<p><strong>Reflection can be slow</strong><br />
Honestly, when I first started working on this demo I was sort of turned off by the use of Reflection myself. After weighing the possible performance loss against the gains in both readability and maintenance I decided this was definitely worth it. I haven&#8217;t performance tested this code so, as always YMMV.</p>
<p>As always, if I screwed up or there is a better way to do this, please let me know in the comments.</p>
<p><a href="http://www.box.net/shared/1q4bq5scuz" target="_blank">Download the source code mentioned in this blog post.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2009/06/22/w-o-m-m-4-asp-mvc-route-attributes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://itc.conversationsnetwork.org/audio/download/ITC.SO-Episode54-2009.05.20.mp3" length="33894437" type="audio/mpeg" />
		</item>
		<item>
		<title>Debugging &quot;Syntax Error&quot; from a bad WebResource.axd request</title>
		<link>http://codeimpossible.com/2009/04/24/debugging-syntax-error-from-a-bad-webresourceaxd-request/</link>
		<comments>http://codeimpossible.com/2009/04/24/debugging-syntax-error-from-a-bad-webresourceaxd-request/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 02:05:48 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=427</guid>
		<description><![CDATA[&#8220;Syntax Error, Line: 2, Char: 0&#8243;. How many of you out there have seen this error while working on a web project?
Usually it&#8217;s because of a forgotten semi-colon or parenthesis in some external javascript file. But sometimes it&#8217;s something more sinister&#8230; Something darker, dirtier and just a little bit more evil.
After seeing the error message, [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;Syntax Error, Line: 2, Char: 0&#8243;. How many of you out there have seen this error while working on a web project?</p>
<p>Usually it&#8217;s because of a forgotten semi-colon or parenthesis in some external javascript file. But sometimes it&#8217;s something more sinister&#8230; Something darker, dirtier and just a little bit more evil.</p>
<p>After seeing the error message, I opened up Internet Explorer&#8217;s options dialog and unchecked the following options:</p>
<ul>
<li>Disable script debugging (Internet Explorer)</li>
<li>Disable script debugging (Other)</li>
</ul>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-456" title="Internet Explorer Options Dialog" src="http://wpup.codeimpossible.com/2009/04/internet_explorer_options_2.jpg" alt="Internet Explorer Options Dialog" width="415" height="521" /></p>
<p>I then closed IE, returned to Visual Studio, stopped and re-started debugging (ctrl+shift+F5), and watched Solution Explorer as my page began to load.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-442" title="Solution Explorer Debugging Internet Explorer" src="http://wpup.codeimpossible.com/2009/04/solution_explorer.png" alt="Solution Explorer Debugging Internet Explorer" width="309" height="265" /></p>
<p>Oh! That&#8217;s not good. See the WebResource.axd request that has the same icon as the Default.aspx file? That means that a bad request was sent for an embedded resource and &#8211; most likely recieved a 404 page back instead of the javascript file, which caused our syntax error.</p>
<p>Ok, so how do we figure out which WebResource reference caused the problem? Well, the only way that I have come up with so far, is to manually copy and paste each WebResource.axd url from the html source of the page to the address bar and navigate there. The pages that give return a file download are ok and the ones that don&#8217;t will return a 404 page in the browser.</p>
<p>After finishing this long process of elimination, I found the resource request that was causing my headache:</p>
<pre class="brush:html">/WebResource.axd?d=MaCiPhUUtdXNj16OOucV5e5lHCBZO...SNIP...</pre>
<p>So how do we figure out which resource has embedded this troublesome URL into our html source? I found the solution to that in <a href="http://blogs.msdn.com/irenak/archive/2006/11/03/sysk-233-how-to-decrypt-an-asp-net-encrypted-data.aspx">Irena Kennedy&#8217;s blog post on &#8220;How to Decrypt an ASP.NET Encrypted Data&#8221;</a>:</p>
<blockquote><p>Please note, that the code below should not be used in production code!  It’s only meant for debugging and troubleshooting, and it may break in future versions of the .NET framework if DecryptString private method changes.</p>
<ol>
<li>Add a web page (e.g. DecryptData.aspx) to your web application.  For the code to work, it must run in the same appdomain as the web application that created your encrypted string.</li>
<li>Add a text box where you will type in the encrypted string.</li>
<li>Add a label where you’ll display decrypted results.</li>
<li>Add a button.</li>
<li>In code-behind on button click event, add the following code:</li>
</ol>
</blockquote>
<pre class="prettyprint"><code>
System.Reflection.BindingFlags bf =
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Static;

System.Reflection.MethodInfo DecryptString =
    typeof(System.Web.UI.Page).GetMethod("DecryptString", bf);

DecryptedData.Text = DecryptString.Invoke(
    null,
    new object[] { EncryptedData.Text } ) as string;

</code></pre>
<p>After I created this page, I pasted the WebResource.axd URL (everything up to the &amp;t=) into the DecryptedData textbox on my DecryptData.aspx page, clicked the Decrypt button, and saw that one of my custom aspx controls was responsible. I then corrected the resource path and the page loaded as it should.</p>
<p>See the screenshot below for an example of the DecryptData page, or <a href="http://www.box.net/shared/uc9aea3999" target="_blank">download the DecryptData .ASPX and Codebehind from my box.net folder</a>.</p>
<p style="text-align: center;"><a href="http://wpup.codeimpossible.com/2009/04/decryption_page.png" target="_blank"><img class="aligncenter size-medium wp-image-445" title="DecryptData page" src="http://wpup.codeimpossible.com/2009/04/decryption_page.png?w=300" alt="DecryptData page" width="300" height="219" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2009/04/24/debugging-syntax-error-from-a-bad-webresourceaxd-request/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>W.O.M.M. weekly post #3 &#8211; HtmlHelper.Gravatar</title>
		<link>http://codeimpossible.com/2009/04/18/womm-weekly-post-3-htmlhelpergravatar/</link>
		<comments>http://codeimpossible.com/2009/04/18/womm-weekly-post-3-htmlhelpergravatar/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 05:32:12 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=292</guid>
		<description><![CDATA[Long story short: I hate re-inventing the wheel. If there is a free service that does something I need I will try my hardest to get that service into whatever I am working on. I&#8217;m currently working on an Asp .Net MVC project that needs Avatars (you know, those funny little pictures next to peoples [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="works-on-my-machine-starburst" src="http://wpup.codeimpossible.com/2009/06/works-on-my-machine-starburst.jpg" alt="works-on-my-machine-starburst" />Long story short: I <b>hate</b> re-inventing the wheel. If there is a free service that does something I need I will try my hardest to get that service into whatever I am working on. I&#8217;m currently working on an Asp .Net MVC project that needs Avatars (you know, those funny little pictures next to peoples names on Twitter). Enter <a href="http://www.gravatar.com">Gravatar</a>.<br />
<br />
Gravatar is an awesome service for anyone looking to add avatars to their apps. It&#8217;s free, incredibly simple to implement, and removes a lot of the hassle around getting avatar support into your web/windows app.</p>
<p>Adding Gravatar support to an application is pretty simple. Can you get a users email address? Can you MD5 said email address? Can you make an HTTP GET? BANG. You sir, or madam, can have Gravatars.</p>
<p>This week for the W.O.M.M. code sample I&#8217;d like to show how I integrated gravatar support into an Asp .Net MVC application.</p>
<h3>How Gravatar Works In A Nutshell</h3>
<p>Gravatar is a free service where you sign up and link images to one or more email addresses that you provide.</p>
<p>Once you link an image to an email address, any application that supports getting an image over the internet can show your Gravatar by making a request to a special URL. This URL is generated by combining an MD5 hash of your email address with some other parameters and the end result is a link to your Gravatar image.</p>
<p>IE: the link to my Gravatar on the right of this page is:</p>
<p><code></p>
<p>http://www.gravatar.com/avatar/15559d868ec27b8583f42116a6b96c14?s=140</p>
<p></code></p>
<p>So 15559d868ec27b8583f42116a6b96c14 is the hash of my email address &#8211; don&#8217;t worry it&#8217;s a one-way hash. The &#8220;s&#8221; parameter is the size of the image that I want, in this case 140 pixels.</p>
<p>That is pretty much it as far as how the system works, but if you want to read more, check out <a href="http://en.gravatar.com/site/implement">Gravatar&#8217;s implementation documentation</a>.</p>
<h3>The Goal</h3>
<p>What I wanted was an HtmlHelper extension method that I could use in my view pages to create an IMG tag with the correct Gravatar URL. After <a href="http://en.gravatar.com/site/implement/url">looking at the documentation on Gravatars &#8220;How the URL is constructed&#8221; page</a>, I decided my helper extension should support the following:</p>
<p><b>Avatar Size (the &#8220;s&#8221; parameter)</b><br />
When making a Gravatar URL you can specify a specific size for the Gravatar image. The size can be anything from 1 to 512 pixels, but the default is 80.</p>
<p><b>Default Avatars (the &#8220;d&#8221; parameter)</b><br />
If the email address you are using doesn&#8217;t have any Gravatars setup, Gravatar will generate one for you by default. You can choose from 3 predefined Gravatar types or you can include a URL to a custom avatar of your own. The predefined Gravatar types are Identicon, Wavatar, and Monsterid.</p>
<p><b>Rating (the &#8220;r&#8221; parameter)</b><br />
This wasn&#8217;t a requirement for what I was working on, but you can designate the maximum &#8220;rating&#8221; of the avatars that Gravatar will generate. The accepted values are &#8220;g&#8221;, &#8220;pg&#8221;, &#8220;r&#8221;, and &#8220;x&#8221; and they are inclusive, so specifying &#8220;r&#8221; will allow &#8220;g&#8221; and &#8220;pg&#8221; rated Gravatars to be generated. Gravatars that are rated &#8220;x&#8221; will be returned as one of the predefined avatars above. The default rating is &#8220;g&#8221;.</p>
<h3>The Code</h3>
<p>Okay, so now I know what I need to support. Now it&#8217;s just a matter of getting the code to do this. Let&#8217;s take a look at the class file I used to get this done.</p>
<pre class="prettyprint"><code>
namespace System.Web.Mvc
{
    using System;
    using System.Web.Routing;
    using System.Web.Security;

    public enum GravatarDefaultTypes
    {
        Identicon,
        Wavatar,
        Monsterid,
        Custom
    }

    public static class GravatarExtension
    {
		public static string Gravatar(
			this HtmlHelper hh,
			string emailAddress,
			int size,
			GravatarDefaultTypes defaultType,
			string customImageUrl,
			RouteValueDictionary htmlAttributes)
        {
            var tagBuilder = new TagBuilder("img");
            string url = "http://www.gravatar.com/avatar/{0}?d={1}&#038;s={2}";

	    // thanks to jon galloway for this one-liner!
            // http://www.eggheadcafe.com/aspnet/how-to/141740/adding-gravatars-to-your.aspx
            string hash = FormsAuthentication
				.HashPasswordForStoringInConfigFile(emailAddress, "MD5");
            string defImg = defaultType.ToString().ToLower();

            if (defaultType == GravatarDefaultTypes.Custom)
            {
                defImg = System.Web
					.HttpUtility
					.UrlEncode(customImageUrl);
            }

            url = String.Format(
                url,
                hash.ToLower(),
                defImg,
                size.ToString());

            tagBuilder.MergeAttributes(htmlAttributes);
            tagBuilder.MergeAttribute("src", url);

            return tagBuilder.ToString(TagRenderMode.Normal);
        }
    }
}
</code></pre>
<p>So you can see I&#8217;m not storing the hash of the email address, instead I am going to pass in the unaltered string. I didn&#8217;t want to have another piece of data to update when the user changed their email address so the Gravatar() method takes an email address and encodes it using a call to FormsAuthentication.HashPasswordForStoringInConfigFile(), which is awesome ( Thanks Jon, you rock!).</p>
<p>Also, I&#8217;m not sure if this is a no-no or what, but I did put the extension class under the System.Web.Mvc namespace. This was mainly a convenience (read: laziness) thing and can be easily changed.</p>
<p>Alright so we have some code now, let&#8217;s take a look at how it can be used in our views.</p>
<pre class="prettyprint"><code>
    &lt;%= Html.Gravatar(
        	Model.Email, // the email address
        	50, // size, in pixels of the avatar
        	GravatarDefaultTypes.Identicon,
        	null,
        	new RouteValueDictionary(new {
        		style = "vertical-align: middle;"
        	})
    )%> 
    <b> &lt;%= Model.UserName %> </b>
</code></pre>
<p>Let&#8217;s see how that looks.</p>
<p><img src="http://wpup.codeimpossible.com/2009/04/user-avatar.png" alt="user-avatar" title="user-avatar" width="84" height="81" class="size-full wp-image-378" /></p>
<p>Booyah, avatar support in 55 lines of code. As always, if I screwed up or there is a better way to do this, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2009/04/18/womm-weekly-post-3-htmlhelpergravatar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing JsonResult in Asp.net MVC</title>
		<link>http://codeimpossible.com/2009/03/16/testing-jsonresult-in-aspnet-mvc/</link>
		<comments>http://codeimpossible.com/2009/03/16/testing-jsonresult-in-aspnet-mvc/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 00:23:22 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://codeimpossible.com/?p=340</guid>
		<description><![CDATA[So lately I&#8217;ve been working on a project using Asp.net MVC and TDD to build a web 2.0 application. It&#8217;s a twitter-like application that I started a while ago but due to my failure to test everything I lost about 99% of my work and had to start over from scratch.
But this was sort of [...]]]></description>
			<content:encoded><![CDATA[<p>So lately I&#8217;ve been working on a project using Asp.net MVC and TDD to build a web 2.0 application. It&#8217;s a twitter-like application that I started a while ago but due to <a href="" title="Test Everything!">my failure to test everything</a> I lost about 99% of my work and had to start over from scratch.</p>
<p>But this was sort of a good thing because it gave me a chance to revisit a lot of things that I wasn&#8217;t very happy with the first time around. I just got done adding the ability for users to post new messages via AJAX.</p>
<p>In the first version of the application a user would type their status into a textbox, click submit and the page would refresh with their new message at the top of their user wall. Although functional this wasn&#8217;t exactly very &#8220;web 2.0&#8243;-ish.</p>
<p>My controller will have an action called Index that takes two parameters, the message the users is posting and the tags associated with that message. m_UserService, and m_MessageService are private objects, that interact with the database.</p>
<pre class="brush:csharp">
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string message, string[] tags)
{

	var messageOwner = this.m_UserService
		.GetByUserName(User.Identity.Name);

	var messageObj = new Message()
	{
		Owner = new User()
		{
			Identifier = messageOwner.Identifier,
			UserName = messageOwner.UserName,
			Email = messageOwner.Email,
			RealName = messageOwner.RealName,
			IsModerator = messageOwner.IsModerator
		},
		Body = message,
		CreatedOn = DateTime.Now,
		IsReply = message.StartsWith("@")
	};

	this.m_MessageService.Post(messageObj);

	return Json(messageObj);
}
</pre>
<p>The JsonResult will be serialized/deserialized by the MVC framework when the code is run in a web project or IIS but I need to be able to test this as part of our build process.</p>
<p><i>* NOTE: For those of you who might be thinking &#8220;how do we get around the authorization&#8221;? I&#8217;ll answer that in a later post (or you can <a href="http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx">check out Scott Hanselmans blog for the solution</a>).</i></p>
<p>Ideally I wanted to do something like the following in my test:</p>
<pre class="brush:csharp">
	Assert.AreEqual("some text", jsonObject.someproperty);
</pre>
<p>But since C# is a type-safe language this isn&#8217;t easily doable. However, utilizing an extension method and the JavaScriptSerializer in System.Web.Script.Serialization we can come pretty close:</p>
<pre class="brush:csharp">
	Assert.AreEqual("some text", jsonObject["someproperty"]);
</pre>
<p>Here is the code I used to achieve this (This code depends on <a href="http://code.google.com/p/moq/">Moq v3.0.108.5 which you can download here</a>):</p>
<pre class="brush:csharp">
using System;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Mvc;

using Moq;

public static class JsonResultExtensions
{

	public static T Deserialize&lt;T>(this JsonResult json,
		Controller controller)
	{

		var jsonSB = new StringBuilder();

		var httpResponseMock =
			new Mock&lt;httpResponseBase>();

		httpResponseMock.Setup(mock => {
			mock.Write(It.IsAny&lt;string>());
		}).Callback&lt;string>((s) => {
			jsonSB.Append(s);
		});

		var httpContextMock =  new Mock&lt;httpContextBase>();

		httpContextMock.Setup(mock => mock.Response)
			.Returns(httpResponseMock.Object);

		controller.ControllerContext
			.HttpContext = httpContextMock.Object;

		jsonResult.ExecuteResult(
			controller.ControllerContext);

		return new JavaScriptSerializer()
			.Deserialize&lt;T>(jsonSB.ToString());
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2009/03/16/testing-jsonresult-in-aspnet-mvc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Jquery + MVC = Web Dev Heaven</title>
		<link>http://codeimpossible.com/2008/10/02/jquery_plus_mvc_equals_web_dev_heaven/</link>
		<comments>http://codeimpossible.com/2008/10/02/jquery_plus_mvc_equals_web_dev_heaven/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 02:43:35 +0000</pubDate>
		<dc:creator>Jared</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://pistalwhipped.wordpress.com/?p=216</guid>
		<description><![CDATA[So Jquery is going to become part of Asp.net MVC. First off, congrats to the Jquery team. They&#8217;ve put out a really awesome product. Second, congrats to Microsoft for catching every .Net developer completely by surprise, proving, again, that they are listening to the community.
I never really got into the microsoft javascript libraries that shipped [...]]]></description>
			<content:encoded><![CDATA[<p>So <a href="http://www.hanselman.com/blog/jQueryToShipWithASPNETMVCAndVisualStudio.aspx" target="_blank">Jquery is going to become part of Asp.net MVC</a>. First off, congrats to <a href="http://jquery.com/" target="_blank">the Jquery team</a>. They&#8217;ve put out a really awesome product. Second, congrats to Microsoft for catching every .Net developer completely by surprise, proving, again, that they are listening to the community.</p>
<p>I never really got into the microsoft javascript libraries that shipped with the ajax control toolkit because I found that I could do things much faster using external javascript libraries .</p>
<p>It will be interesting to see what Microsoft contributes back to the Jquery community in later updates to the ASP MVC product.</p>
]]></content:encoded>
			<wfw:commentRss>http://codeimpossible.com/2008/10/02/jquery_plus_mvc_equals_web_dev_heaven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
