<?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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Diary of a Ninja</title><link>http://www.diaryofaninja.com</link><description>A blog about life, code and beating level 99 to brag to your mates.</description><language>English</language><copyright>Doug Rathbone</copyright><pubDate>5/12/2012 9:38:13 PM</pubDate><feedburner:info uri="diaryofaninja" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/2.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-nc-sa/2.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://www.diaryofaninja.com/rss/main" /><feedburner:emailServiceId>DiaryOfANinja</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://www.diaryofaninja.com/rss/main" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Fwww.diaryofaninja.com%2Frss%2Fmain" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item><title>Writing your own custom ASP.Net MVC [Authorize] attributes</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/zOFBY7Wj__U/writing-your-own-custom-aspnet-mvc-authorize-attributes</link><description>&lt;p&gt;ASP.Net’s [Authorize] attribute is another cool feature that makes it easy to add authentication at the Controller level when building a website, but the real goldmine here is that like nearly everything else in ASP.Net MVC, you can pick apart the functionality and extend it yourself – In this post we will take a look at creating our own custom Authentication attribute.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/48bcc826-2926-4122-9528-58d0fff6dfcc_image_a0212ce5-2c56-4e25-866d-662107aa1735.png" width="290" height="92" /&gt;Lately I have been involved in a number of projects that have used ASP.Net MVC as the primary web service platform because of its awesome REST based approach to controllers – WCF fans out there may be shocked to hear this, but i truly believe that building as website is a pretty solution agnostic task, and ASP.Net MVC allows us to get a lot closer to how the rest of the world thinks about “web services” in the sense that your service really is&lt;em&gt; just another end point of your website&lt;/em&gt; just one that returns JSON or XML and therefore doesn’t really need the differentiation of being a “separate thing/entity” to your website (i.e. Web site/Web service).&lt;/p&gt;  &lt;p&gt;ASP.Net MVC has another really neat feature tucked up its sleave when it comes to security in the form of the [Authenticate] attribute (if you have never heard of this head on over to &lt;a href="http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication-cs"&gt;ASP.net to take a look at a quick tutorial&lt;/a&gt;). The ability to have granular security baked-in at the class or method level in a controller really appeals to me, so ASP.Net MVC’s [Authenticate] attribute/annotation ticks all the right boxes by allowing you to easily hook into the ASP.Net membership provider.&lt;/p&gt;  &lt;p&gt;The real question is; What about when you want to take an even more granular approach to the membership/[Authorize] implementation? I have seen a few developers who when facing this task start hacking the extra security into their Controller method’s code – this is not where it should be done. The primary reason for this is the fact that if you are using ASP.Net’s caching in your controllers, the ActionResult will be cached and your controller code will not even be hit!&lt;/p&gt;  &lt;h3&gt;What ASP.Net MVC Controller Action authentication looks like&lt;/h3&gt;  &lt;p&gt;The following code snippet is from the standard ASP.Net MVC project’s AccountController showing the &lt;strong&gt;[Authorize]&lt;/strong&gt; attribute being used to enforce security in the user account section of the website:&lt;/p&gt;  &lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;Authorize&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangePassword(&lt;span style="color: #2b91af"&gt;ChangePasswordModel &lt;/span&gt;model)
{
    &lt;span style="color: blue"&gt;...&lt;/span&gt;
}&lt;/pre&gt;

&lt;p&gt;The above annotation is used to let the ASP.Net MVC framework know you want to check a user is authenticated before processing the controller action – this authentication check is done even if the result of the controller action is cached (as i mentioned above this is a really important thing to point out, as if you placed your authentication inside your controller and wanted to perform caching on your output you would have to build your own caching).&lt;/p&gt;

&lt;h3&gt;Anatomy of an [Authorize] attribute&lt;/h3&gt;

&lt;p&gt;When you place the [Authorize] attribute on a Controller’s action method, a couple of calls get made to the AuthorizeAttribute class at the beginning of each request to your controller to authenticate users. There is a lot of code in the MVC framework’s AuthorizeAttribute class, but the lines containing the methods we really care about are the following (as pulled from the Microsoft AuthorizeAttribute source using .Net Reflector):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public virtual void &lt;/span&gt;OnAuthorization(&lt;span style="color: #2b91af"&gt;AuthorizationContext &lt;/span&gt;filterContext)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(filterContext == &lt;span style="color: blue"&gt;null&lt;/span&gt;)
    {
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;filterContext&amp;quot;&lt;/span&gt;);
    }

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(AuthorizeCore(filterContext.HttpContext))
    {
        &lt;span style="color: green"&gt;// ** IMPORTANT **
        // Since we're performing authorization at the action level, the authorization code runs
        // after the output caching module. In the worst case this could allow an authorized user
        // to cause the page to be cached, then an unauthorized user would later be served the
        // cached page. We work around this by telling proxies not to cache the sensitive page,
        // then we hook our custom authorization code into the caching mechanism so that we have
        // the final say on whether a page should be served from the cache.

        &lt;/span&gt;&lt;span style="color: #2b91af"&gt;HttpCachePolicyBase &lt;/span&gt;cachePolicy = filterContext.HttpContext.Response.Cache;
        cachePolicy.SetProxyMaxAge(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;TimeSpan&lt;/span&gt;(0));
        cachePolicy.AddValidationCallback(CacheValidateHandler, &lt;span style="color: blue"&gt;null &lt;/span&gt;&lt;span style="color: green"&gt;/* data */&lt;/span&gt;);
    }
    &lt;span style="color: blue"&gt;else
    &lt;/span&gt;{
        HandleUnauthorizedRequest(filterContext);
    }
}

&lt;span style="color: green"&gt;// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
&lt;/span&gt;&lt;span style="color: blue"&gt;protected virtual bool &lt;/span&gt;AuthorizeCore(&lt;span style="color: #2b91af"&gt;HttpContextBase &lt;/span&gt;httpContext)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(httpContext == &lt;span style="color: blue"&gt;null&lt;/span&gt;)
    {
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;httpContext&amp;quot;&lt;/span&gt;);
    }

    &lt;span style="color: #2b91af"&gt;IPrincipal &lt;/span&gt;user = httpContext.User;
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(!user.Identity.IsAuthenticated)
    {
        &lt;span style="color: blue"&gt;return false&lt;/span&gt;;
    }

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(_usersSplit.Length &amp;gt; 0 &amp;amp;&amp;amp; !_usersSplit.Contains(user.Identity.Name, &lt;span style="color: #2b91af"&gt;StringComparer&lt;/span&gt;.OrdinalIgnoreCase))
    {
        &lt;span style="color: blue"&gt;return false&lt;/span&gt;;
    }

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(_rolesSplit.Length &amp;gt; 0 &amp;amp;&amp;amp; !_rolesSplit.Any(user.IsInRole))
    {
        &lt;span style="color: blue"&gt;return false&lt;/span&gt;;
    }

    &lt;span style="color: blue"&gt;return true&lt;/span&gt;;
}&lt;/pre&gt;


&lt;p&gt;The great thing is the AuthorizeAttribute class shown above can be inherited from and the methods above can be overridden to allow us to disable the authentication checks for the example i have for you below. &lt;em&gt;These same methods can be used to add special authentication checks or anything else you desire&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;An Example: A Switchable Authorize Attribute&lt;/h3&gt;

&lt;p&gt;When creating web services with ASP.Net MVC I have often been in situations where there has been a need to turn off authentication during development for access by Silverlight/Flash/JavaScript requests on the client side is pretty much a necessity to avoid drawing out the development/wasting time from liaison with other developers un-necessarily. &lt;/p&gt;

&lt;p&gt;The example I’m going to take you through solves this in the form of a switchable [Authorization] attribute that will allow you to turn off authentication when the solution is built in DEBUG mode (i.e. during development). This will allow developers working with the site during development to test web service endpoints without having to log in every time they want to test. You could change this to run from an AppSetting property but i recommend against this as it is a pretty big vulnerability if either it doesn’t get set by developers at deployment time, or someone with nefarious intentions changes it once the site is live.&lt;/p&gt;

&lt;p&gt;Custom Attribute class code:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;AttributeUsage&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;AttributeTargets&lt;/span&gt;.Method, AllowMultiple = &lt;span style="color: blue"&gt;false&lt;/span&gt;, Inherited = &lt;span style="color: blue"&gt;true&lt;/span&gt;)]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SwitchableAuthorizationAttribute &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;AuthorizeAttribute
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;protected override bool &lt;/span&gt;AuthorizeCore(&lt;span style="color: #2b91af"&gt;HttpContextBase &lt;/span&gt;httpContext)
    {
        &lt;span style="color: blue"&gt;bool &lt;/span&gt;disableAuthentication = &lt;span style="color: blue"&gt;false&lt;/span&gt;;

        &lt;span style="color: blue"&gt;#if &lt;/span&gt;DEBUG
        &lt;span style="color: gray"&gt;disableAuthentication = true;
        &lt;/span&gt;&lt;span style="color: blue"&gt;#endif

        if &lt;/span&gt;(disableAuthentication)
            &lt;span style="color: blue"&gt;return true&lt;/span&gt;;

        &lt;span style="color: blue"&gt;return base&lt;/span&gt;.AuthorizeCore(httpContext);
    }
}&lt;/pre&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;SwitchableAuthorization&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangePassword()
{
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View();
}
&lt;font face="Calibri"&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;As you can see from the above example’s usage of the overridden &lt;em&gt;AuthorizeCore()&lt;/em&gt; method, when built using Debug mode, the method returns true without asking the membership provider. This will allow Silverlight and Flash developers to test the site’s code from within their IDE when developing.&lt;/p&gt;

&lt;h3&gt;Adding other Attribute awareness&lt;/h3&gt;

&lt;p&gt;An even more powerful addition to the above example is the ability of the &lt;em&gt;OnAuthorization()&lt;/em&gt; method to see the other attributes applied to the class/method at run time – allowing your attribute to change its functionality based on the other attributes applied. In my example i check that the [HttpPost] attribute is applied to the method as well by&amp;#160; checking the count of the attribute.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public override void &lt;/span&gt;OnAuthorization(&lt;span style="color: #2b91af"&gt;AuthorizationContext &lt;/span&gt;filterContext)
{
    &lt;span style="color: green"&gt;//Check that the HttpPost attribute is also applied
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionDescriptor &lt;/span&gt;action = filterContext.ActionDescriptor;
    &lt;span style="color: blue"&gt;bool &lt;/span&gt;isAnHttpPost = action.GetCustomAttributes(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;HttpPostAttribute&lt;/span&gt;), &lt;span style="color: blue"&gt;true&lt;/span&gt;).Count() &amp;gt; 0;

    &lt;span style="color: blue"&gt;base&lt;/span&gt;.OnAuthorization(filterContext);
}&lt;/pre&gt;


&lt;h3&gt;Where to from here?&lt;/h3&gt;

&lt;p&gt;If you take anything from the above post, it has to be yet again how awesome and powerful the ASP.Net MVC framework is. The next time you are looking to add functionality to your ASP.Net MVC site in an elegant manner, think about creating a custom attribute.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BqTEFH2nC24r6yAuVtYTfZrNRYI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BqTEFH2nC24r6yAuVtYTfZrNRYI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BqTEFH2nC24r6yAuVtYTfZrNRYI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BqTEFH2nC24r6yAuVtYTfZrNRYI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=thrRqFZTS-g:6_x1wBS8KmQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=thrRqFZTS-g:6_x1wBS8KmQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=thrRqFZTS-g:6_x1wBS8KmQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=thrRqFZTS-g:6_x1wBS8KmQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/zOFBY7Wj__U" height="1" width="1"/&gt;</description><pubDate>7/24/2011 7:59:31 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/07/24/writing-your-own-custom-aspnet-mvc-authorize-attributes</feedburner:origLink></item><item><title>TeamCity - When 1 build agent just isn’t enough</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/4SRBvScSDA0/teamcity--when-1-build-agent-isnrsquot-enough</link><description>&lt;p&gt;&lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; is one of the greatest tools to hit the Continuous Integration world, with free licensing for 20 build configurations and an easy to use interface it ticks all the right boxes (not to mention ease of use for Windows Users) – but once you splash out on an Enterprise license and grow your installation to house many build configurations you start to want more power, and this is when a second build agent is your ticket to freedom.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/36ea260b-75aa-42f9-a812-801aa9e70360_image_4b7343d6-a6a2-42fa-8db6-dcce7e5ed4f8.png" width="350" height="253" /&gt;At my workplace all projects that we develop require compulsory continuous delivery. Our staging environments auto deploy on check-in and our live environments have only ever been deployed to by our build server not direct from a users machine (they are executed manually) – this way our team always know that deployment day is a walk in the park, and there is no stress or tension when deploying a new feature.&lt;/p&gt;  &lt;p&gt;If you have read &lt;a href="/blog/2011/03/07/another-look-at-continuous-deliverycontinuous-deployment"&gt;my posts&lt;/a&gt; &lt;a href="/blog/2010/12/02/continuous-integration-tip-3-ndash-versioning-your-databases-as-part-of-your-build"&gt;on CI&lt;/a&gt; &lt;a href="/blog/2011/02/12/build-driven-deployment-ndash-the-hot-new-craze-coming-to-a-development-team-near-you"&gt;in the past&lt;/a&gt;, you’ll know that &lt;a href="/blog/2010/05/09/automated-site-deployments-with-teamcity-deployment-projects-amp-svn"&gt;Continuous Integration&lt;/a&gt; and &lt;a href="/blog/2011/03/27/continuous-integration-ndash-itrsquos-all-about-your-build-projects-ecosystem"&gt;Continuous Delivery&lt;/a&gt; are both something i am very passionate in my support of.&lt;/p&gt;  &lt;p&gt;So much so that my workplace’s love for CI and CD has meant that we have over 100 build configurations on our TeamCity server. Our team members will be working on any number of different projects at the same time, and as a result we have multiple projects deploying as part of our Continuous Delivery setup all the time and often at the same time – this can lead to a little friction, as developers can be forced to wait for their project to make it to the front of the build queue.&lt;/p&gt;  &lt;p&gt;So what is the solution? It’s quite simple:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Moar Buildseseseses&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The answer is to have multiple build agents so that you can run more than one build at a time. &lt;/p&gt;  &lt;p&gt;JetBrains in their usual fashion have made the licensing for TeamCity simple and easy to understand when it comes to additional build agents – at the time this article was written, &lt;a href="http://www.jetbrains.com/teamcity/buy/index.jsp"&gt;both FREE Professional version and the Enterprise version allow for 3 build agents included in their licenses&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;This means that even with the FREE version, you can take over the world with your CI awesomeness!&lt;/p&gt;  &lt;p&gt;After finding this out you may be a little disheartened if you run your build server on window though, as the installer for the TeamCity build agent only supports a single instance per server. With modern hardware, even the most minimal/shoved-in-a-back-cupboard/rebuilt-from-your-sisters-old-school-computer servers have more than enough resources to handle multiple build agent instances.&lt;/p&gt;  &lt;p&gt;For non-Windows installations, running multiple build agents on a single machine is quite simple, and JetBrains lists how to do it – the Windows section of this how to relies on you not using an installer though.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;There is a solution though, so “&lt;/em&gt;&lt;/strong&gt;&lt;a href="http://www.urbandictionary.com/define.php?term=Cheer%20Up%20Emo%20Kid"&gt;&lt;strong&gt;&lt;em&gt;Cheer up Emo Kid&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;” – You can install multiple TeamCity Build Agents on a single Windows installation.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;h3&gt;Anatomy of a TeamCity Build Agent&lt;/h3&gt;  &lt;p&gt;TeamCity’s build agent is a single EXE file that runs as a service &lt;em&gt;(it is located at [build agent directory]/launcher/bin/TeamCityAgentService-windows-x86-32.exe).&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The build agent on start up opens a listening port as defined in a configuration file &lt;em&gt;(located at [build agent directory]/conf/buildAgent.properties)&lt;/em&gt; The default port for this is 9090.&lt;/p&gt;  &lt;p&gt;It then contacts it’s nominated TeamCity server (again stored in the above config file), and registers as a build agent (the default name for this agent is the hostname of the server it is installed on).&lt;/p&gt;  &lt;p&gt;The Windows installation of TeamCity’s build agent is quite modular. Below is a screenshot of the Build Agent’s root folder:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML4290947f" border="0" alt="SNAGHTML4290947f" src="http://www.diaryofaninja.com/asset/blogimages/2d355406-7100-4dac-a738-d96917f04e01_SNAGHTML4290947f.png" width="450" height="323" /&gt;&lt;/p&gt;  &lt;p&gt;A quick break down of the folders you’ll want to know about (some of the information below are conclusions made based on digging around, others are from information found on the interwebs):&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/bin&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains all the service control batch files (start service, stop service, install service etc etc)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/conf&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains all the agent’s configuration files/details such as the agents name, its listening port and the address of it’s server.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/launcher&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains all the service’s application files. The bin folder of this actually has all versions of the service not just the Windows one (Solaris, Mac etc)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/logs&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Not too hard to guess…&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/plugins&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains all the Build agents plugins. This includes all the build runners and source control modules.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/temp&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains build task temporary files (actual build run tasks – not artefacts of checked out files&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;/work&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Contains configuration that points at the storage locations of currently running builds (in a file called directory.map).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Why do you care about all the above? You care because they unlock the ability to install more than one agent at a time!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Installing a Second Build Agent on the same server&lt;/h3&gt;  &lt;p&gt;For my example I'll assume you are doing the below as a &lt;em&gt;second installation, &lt;/em&gt;i.e. you have a server that already has TeamCity and a single Build Agent installed (if you don’t and need help, check out my previous post on &lt;a href="/blog/2010/05/09/automated-site-deployments-with-teamcity-deployment-projects-amp-svn"&gt;Automated Deployments with TeamCity&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;On your TeamCity server Download the latest build agent installer&amp;#160; by visiting the Agents tab of your installation and clicking the &lt;em&gt;Install Build Agent&lt;/em&gt; link in the top right corner of the page. When you have downloaded the MS Windows Installer, run it.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/639eed3d-1c61-47ab-aed9-380ca6246038_SNAGHTML42bc1784_1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML42bc1784" border="0" alt="SNAGHTML42bc1784" src="http://www.diaryofaninja.com/asset/blogimages/f4d79c24-0623-44d6-a6d5-72fc185cd214_SNAGHTML42bc1784_thumb.png" width="450" height="61" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a83d64ff-a7bf-4229-b1d3-dfa778fca04a_image_4a86cb97-2925-430f-a6b2-2dc31f285f4e.png" width="404" height="266" /&gt;&lt;/p&gt;  &lt;p&gt;When selecting what to install, stick with the default and install everything by clicking &lt;strong&gt;Next&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/801d2906-3c81-4405-ab23-d82637edfe33_image_027e3147-e564-4e3a-ac8f-3fce1366d881.png" width="450" height="345" /&gt;&lt;/p&gt;  &lt;p&gt;When entering the installation directory, enter a &lt;em&gt;New directory name.&lt;/em&gt;&amp;#160; Make sure this is not the same as your initial build agent installation directory.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a696e9f2-97c9-4c0c-85d6-afd68e8f332f_image_2befc3a0-6375-4ded-b816-510f7af0f35f.png" width="450" height="345" /&gt;&lt;/p&gt;  &lt;p&gt;Click &lt;strong&gt;Next &lt;/strong&gt;and wait for the build agent’s files to be installed in the directory you entered above.&lt;/p&gt;  &lt;p&gt;When complete this will bring up a configuration window. &lt;/p&gt;  &lt;p&gt;In this window you want to:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Enter a name for your build agent &lt;strong&gt;THIS MUST BE DIFFERENT FROM THE BUILD AGENT YOU ALREADY HAVE INSTALLED&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Enter a port for your agent to listen on &lt;strong&gt;THIS MUST BE DIFFERENT FROM THE BUILD AGENT YOU ALREADY HAVE INSTALLED&lt;/strong&gt;&amp;#160; &lt;/li&gt;    &lt;li&gt;Enter the server URL for your TeamCity server – this is &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt; if you are hosting the agent on the same server as TeamCity &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/7d010da5-fefa-41b7-bb3b-13f520276d92_image_7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/97e6f289-dc4a-46e7-a29a-b8650f9a1a40_image_thumb.png" width="450" height="334" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;STOP!!!!!!&lt;/p&gt;    &lt;p&gt;You must complete some manual changes to the configuration files of your new build agent before continuing with the installation. If you click &lt;strong&gt;Save &lt;/strong&gt;button without making them, you will break both your newly installed and old build agents and have to start from scratch. You have been warned!&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;A note about continuing (DO NOT DO THIS YET)&lt;/h3&gt;  &lt;p&gt;The second you click the &lt;strong&gt;Save &lt;/strong&gt;button, and then click &lt;strong&gt;Next, &lt;/strong&gt;the installer runs a batch file to register the build agent EXE as a service – it uses a bunch of configuration settings in the file we are about to edit to complete this. What we need to do is change these configuration settings so that when the service gets registered it installs as a &lt;em&gt;Second Service&lt;/em&gt; instead of just installing over the top of your first build agent.&lt;/p&gt;  &lt;h3&gt;Configuration Changes&lt;/h3&gt;  &lt;p&gt;Open Notepad &lt;strong&gt;as Administrator&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Open the file &lt;em&gt;[BuildAgentDirectory]\launcher\conf\wrapper.conf&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Find the line that reads&lt;/p&gt;  &lt;pre class="code"&gt;# Name of the service
wrapper.ntservice.name=TCBuildAgent&lt;/pre&gt;

&lt;p&gt;And change the settings entries to something unique&lt;/p&gt;

&lt;pre class="code"&gt;# Name of the service
wrapper.ntservice.name=TCBuildAgent2&lt;/pre&gt;

&lt;p&gt;Do the same for the following entries&lt;/p&gt;

&lt;pre class="code&amp;gt;&amp;#13;&amp;#10;# Name of the service&amp;#13;&amp;#10;wrapper.ntservice.name=TCBuildAgent2&amp;lt;/pre&amp;gt;&amp;#13;&amp;#10;&amp;lt;p&amp;gt;Do the same for the following lines&amp;lt;/p&amp;gt;&amp;#13;&amp;#10;&amp;lt;pre class=" code?="code?"&gt;# Title to use when running as a console
wrapper.console.title=TeamCity Build Agent

# Display name of the service
wrapper.ntservice.displayname=TeamCity Build Agent Service

# Description of the service
wrapper.ntservice.description=TeamCity Build Agent Service&lt;/pre&gt;

&lt;p&gt;An example of the values after being altered:&lt;/p&gt;

&lt;pre class="code"&gt;# Title to use when running as a console
wrapper.console.title=TeamCity Build Agent 2

# Display name of the service
wrapper.ntservice.displayname=TeamCity Build Agent Service 2

# Description of the service
wrapper.ntservice.description=TeamCity Build Agent Service 2&lt;/pre&gt;

&lt;p&gt;Now switch back to your installation window and click &lt;strong&gt;Save&lt;/strong&gt; at the settings pane.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/6f653604-a86b-4058-a7b8-e2ee08b87386_image_9.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/36b5c164-0990-40b9-975f-dc1cf206eae8_image_thumb_1.png" width="450" height="334" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back in the installer window Click &lt;strong&gt;Next&lt;/strong&gt; (this will install and register the service using the settings we entered above.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/4a469cc4-be45-44c9-9e0f-f85573c14cfc_image_920c5a7c-50b2-45c7-9771-4ddee9aee894.png" width="450" height="345" /&gt;&lt;/p&gt;

&lt;p&gt;Now click &lt;strong&gt;Next&lt;/strong&gt; again to start your new build agent&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/98e0d244-d824-43e0-9a9c-9fa98d278e6f_image_2d063532-cea9-4326-8acd-0f4062947b09.png" width="450" height="345" /&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Finish&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/bbe5e38e-7be9-414c-bc7b-a573a0022f29_image_609bc616-486e-42fd-a8ac-a054d4b373b3.png" width="450" height="345" /&gt;&lt;/p&gt;

&lt;p&gt;And you are done! &lt;/p&gt;

&lt;p&gt;Time to go get yourself a &amp;lt;insert beverage of choice&amp;gt; to celebrate your new multiple-build-agent glory.&lt;/p&gt;

&lt;h3&gt;Where to from here?&lt;/h3&gt;

&lt;p&gt;There are a few gotcha’s that i have experienced when first moving to having multiple build agents, and they are unrelated to “hacking” this installation process but are just par-for-the-course when working with multiple build agents on a single machine. Either way, you should make yourself aware;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple Builds Running Concurrently&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The out of the box configuration for a TeamCity build configuration allows for unlimited instances of a build config to run concurrently – when all your agents are on a single server you probably do not want this to happen, as they probably share the same source control and may also talk to 3rd part resources such as your integration testing environment so you don’t want multiple instances of this to run at the same time.&lt;/p&gt;

&lt;p&gt;To turn this off, simply set the maximum concurrent build value on the first page of a build configuration’s &lt;em&gt;Edit Configuration Settings&lt;strong&gt; &lt;/strong&gt;&lt;/em&gt;page to 1&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/1df0f16c-13b7-4757-b4b7-4f860935b9cb_image_16.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/1919ac17-050f-4f56-b687-4ef7806ea937_image_thumb_2.png" width="450" height="80" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different Build Configurations Sharing The Same VCS Checkout Folder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another problem i have run into is where you have the same solution being built for multiple environments or being deployed to multiple environments and you have both configurations sharing the same source control check out directory. This causes the builds to hang while they both try to delete/download source/build source from the same folder at the same time.&lt;/p&gt;

&lt;p&gt;To correct this, simply make sure all your build configurations use different VCS/source control check out directories. This is changed from the &lt;em&gt;Version Control Settings&lt;/em&gt; page of your build configuration:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/8884292c-8684-4106-b875-5b660297aff2_image_18.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/082d3d5e-0c97-421a-8d32-5a4b4c3424ec_image_thumb_3.png" width="450" height="108" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_3r7IggLIAfOHuqOMDr4LMV5xLc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_3r7IggLIAfOHuqOMDr4LMV5xLc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_3r7IggLIAfOHuqOMDr4LMV5xLc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_3r7IggLIAfOHuqOMDr4LMV5xLc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=FWk3udLjuJI:NGS8uRc3Ph8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=FWk3udLjuJI:NGS8uRc3Ph8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=FWk3udLjuJI:NGS8uRc3Ph8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=FWk3udLjuJI:NGS8uRc3Ph8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/4SRBvScSDA0" height="1" width="1"/&gt;</description><pubDate>7/26/2011 8:58:03 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/07/26/teamcity--when-1-build-agent-isnrsquot-enough</feedburner:origLink></item><item><title>Build Accessible web sites with Visual Studio – WCAG reporting</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/MXvo9irLT2Q/build-accessible-web-sites-with-visual-studio-ndash-wcag-reporting</link><description>&lt;p&gt;Adding Accessibility to a website for access by sight or hearing impaired users is a thought that many developers have post build. Along with this, when you’re tasked with the job of building an accessible website, Visual Studio probably wouldn’t initially be a tool that comes to mind, but Visual Studio has everyone fooled on this topic as it has this functionality covered, you just need to look a little below the surface.&lt;/p&gt;  &lt;h3&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/971a4ac9-84d4-4a82-97d9-c20773897cbf_image_e435b7a8-27e2-4e63-8fb6-76c0e76954e2.png" width="300" height="201" /&gt;Accessibility?&lt;/h3&gt;  &lt;p&gt;The World Wide Web Consortium is an international community that develops standards for the internet. A part of this entails building standards on accessibility, so that hearing and sight impaired users can enjoy the internet just as much everyone else &lt;em&gt;(LOL cats included). &lt;/em&gt;Making your website accessible should be considered best practice, in the same way that placing wheelchair access at a public venue is, and seeing i feel the internet should be probably be &lt;em&gt;more&lt;/em&gt; accessible that any physical venues, taking the time the implement these standards definitely helps work towards this goal.&lt;/p&gt;  &lt;p&gt;The smart people at the W3C have come up with a great set of guidelines that are referred to as the &lt;a href="http://www.w3.org/TR/WCAG20/"&gt;WCAG&lt;/a&gt;. These checklists give developers an easy way to make sure the site they are building is accessible. &lt;/p&gt;  &lt;p&gt;There are two progressive levels of accessibility in the WCAG checklist from the W3C, marked as Priority 1 and Priority 2. With these staged checklists is becomes easier to implement a staged roll out of accessibility to a site. Even with these checklists, when building large sites with hundreds of pages, the job of checking each item off against your encyclopaedia of pages can be hard to stomach.&lt;/p&gt;  &lt;p&gt;This very need has lead to the creation of many different tools to help you scan your site to validate it against these lists – Visual Studio is one of these tools thanks to a nifty little feature that, though not many developers know it, allows you to check your site against the WCAG list without having to leave your favourite IDE.&lt;/p&gt;  &lt;h3&gt;Shut up and show me already…&lt;/h3&gt;  &lt;p&gt;&lt;em&gt;The Visual Studio tool I show you below can be used in a couple of different ways. A lot of people use this tool on ASP.Net pages before they publish their website. I suggest against this and instead suggest you cut &amp;amp; paste out of the actual output of your page as there can be differences that you miss when validating against a pre-run time page.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Load the page you want to validate against the WCAG lists in your favourite web browser. &lt;/p&gt;  &lt;p&gt;Conduct the usual &lt;em&gt;View Source&lt;/em&gt; in your browser of your page and copy the source code to the clipboard.&lt;/p&gt;  &lt;p&gt;Open Visual Studio and Select &lt;strong&gt;File &amp;gt; New File&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/ba0f2bfe-4e7f-4ce0-904b-962e93d75943_image_fd1fac47-ff8e-4ae6-a50a-63f843dbd580.png" width="322" height="183" /&gt;&lt;/p&gt;  &lt;p&gt;Select &lt;strong&gt;HTML Page&lt;/strong&gt; and click OK&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/67d489b6-4814-4f2b-b706-aea8dba3dc0f_image_b8784705-85fd-4694-be8c-292f997b7657.png" width="450" height="153" /&gt;&lt;/p&gt;  &lt;p&gt;Open the Source View of the new HTML page in Visual Studio&lt;/p&gt;  &lt;p&gt;Paste the source code that you copied above in your web browser into the source code of your new HTML page&lt;/p&gt;  &lt;p&gt;&lt;em&gt;(Now comes the secret)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Select &lt;strong&gt;Tools &amp;gt; Check Accessibility&lt;/strong&gt; to open the WCAG checker&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/e4c2d852-3261-488f-96bc-f4d8887ad4aa_image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/0d433c47-815c-467a-adae-0c657bd968c1_image_thumb.png" width="450" height="164" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now select all the &lt;strong&gt;Priority&lt;/strong&gt; items you want to validate the page against and click &lt;strong&gt;Validate&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/f082136a-9e5e-4725-bf12-aa6c81df50dc_image_9af853c4-6d4a-46a6-94c6-5ad91771caa7.png" width="345" height="319" /&gt;&lt;/p&gt;  &lt;p&gt;In the Error and Warning pane at the bottom of your IDE pane you can review all the WCAG Priority exceptions individually. Clicking on one of the items will take you to the exception in your&amp;#160; page’s HTML.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/88e1715b-a94a-4d70-a071-41dd5f8a2422_image_8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/0bd9fbb8-1bac-46f8-9ef7-301a0853d3d3_image_thumb_1.png" width="450" height="151" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;(If you have moved this pane somewhere else on the screen you’ll have to refer to it at your new location instead)&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Too easy!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/03tfuAbpofiV-TMRofQqiz2WEAk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/03tfuAbpofiV-TMRofQqiz2WEAk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/03tfuAbpofiV-TMRofQqiz2WEAk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/03tfuAbpofiV-TMRofQqiz2WEAk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=CZIYblIW6aw:nR8QsHq01i8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=CZIYblIW6aw:nR8QsHq01i8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=CZIYblIW6aw:nR8QsHq01i8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=CZIYblIW6aw:nR8QsHq01i8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/MXvo9irLT2Q" height="1" width="1"/&gt;</description><pubDate>8/1/2011 7:48:19 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/08/01/build-accessible-web-sites-with-visual-studio-ndash-wcag-reporting</feedburner:origLink></item><item><title>Using Custom Web.config Transformations in MSBUILD</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/i7a7u00Ec1Y/using-custom-webconfig-transformations-in-msbuild</link><description>&lt;p&gt;Web.config transformations have been around for a while now, and a lot of developers use them in their staple day-to-day environment deployment strategies – hell, Scott Hanselman was spouting about them way back in the beginning on 2010 with his “&lt;a href="http://www.hanselman.com/blog/WebDeploymentMadeAwesomeIfYoureUsingXCopyYoureDoingItWrong.aspx"&gt;Web Deployment Made Awesome: If you’re using XCOPY, you’re doing it wrong&lt;/a&gt;” post. As usual though, one size does not fit all – and in the case of Continuous Integration fans out there that may have specific build-configuration-based build and deployment scenarios (such as myself), there is the need to have finer grained control over the Web.config transformation process. If this sounds like you, then this post is aimed to deliver.&lt;/p&gt;  &lt;h3&gt;What a second… what the hell are “Web.config Transforms”?&lt;/h3&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/50579ddb-0d06-4e5b-917b-0a2beed2aa6f_image_cbdce000-ebe0-4485-80d8-d0b8f51d5ae3.png" width="303" height="96" /&gt;ASP.net has had a few features that that been around for what seems like forever when it comes to abstracting away or alternating between different configuration data for your website (i’m talking about &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx"&gt;configSource&lt;/a&gt;&lt;/strong&gt; functionality mostly). The features were very minimal and usually created a less-than-ideal solution for developers working on big websites in multiple environments. With the advent of Visual Studio 2010 Microsoft kindly helped us all out by taking note that “&lt;em&gt;hey maybe not all websites are being built for a single server with a single configuration&lt;/em&gt;”… &lt;strong&gt;Smart guys&lt;/strong&gt;. They created &lt;a href="http://msdn.microsoft.com/en-us/library/dd465318.aspx"&gt;web.config transformations&lt;/a&gt; to help deal with this problem and Jokes aside, the feature is actually pretty cool and allows you to write a base web.config file as you normally would and then &lt;em&gt;transform&lt;/em&gt; it for each of your environments.&lt;/p&gt;  &lt;p&gt;Your base web.config:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;appSettings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;key&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ExampleApplicationSetting&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Value being replaced by Transform&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;appSettings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;MyConnectionString&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;connectionString&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;...&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;providerName&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Data.SqlClient&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;customErrors &lt;/span&gt;&lt;span style="color: red"&gt;mode&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Off&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation &lt;/span&gt;&lt;span style="color: red"&gt;debug&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Your web.config transform (note the change to my connection string, my custom errors and my compilation mode):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration &lt;/span&gt;&lt;span style="color: red"&gt;xmlns:xdt&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/XML-Document-Transform&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;appSettings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;key&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ExampleApplicationSetting&lt;/span&gt;&amp;quot;
                 &lt;span style="color: red"&gt;xdt:Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;SetAttributes(value)&lt;/span&gt;&amp;quot;
                 &lt;span style="color: red"&gt;xdt:Locator&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Condition(@key='ExampleApplicationSetting')&lt;/span&gt;&amp;quot;
                 &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The new value to replace after transform&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;appSettings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;MySolutionDatabase&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;xdt:Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Replace&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;xdt:Locator&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Condition(@name='MySolutionDatabase')&lt;/span&gt;&amp;quot;
                 &lt;span style="color: red"&gt;connectionString&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;... My New Connection String ...&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;providerName&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Data.SqlClient&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;customErrors &lt;/span&gt;&lt;span style="color: red"&gt;xdt:Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Replace&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;mode&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;RemoteOnly&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation &lt;/span&gt;&lt;span style="color: red"&gt;xdt:Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;SetAttributes(debug)&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;debug&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;If this is the first you’ve heard of web.config transforms and the syntax in my example above isn’t the clearest it could be, you’ll find the &lt;a href="http://msdn.microsoft.com/en-us/library/dd465326.aspx"&gt;MSDN page on the transformation syntax&lt;/a&gt; a valuable read.&lt;/p&gt;

&lt;h3&gt;So what is wrong with the default usage?&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“So what?”&lt;/em&gt;&amp;#160; you say, “&lt;em&gt;I use them every day, and they work fine”&lt;/em&gt;. The main problem i have with the “out of the box solution” is as follows;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The default usage creates a new config transform for each build configuration &lt;em&gt;of the website they sit inside&lt;/em&gt;. &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When using Visual Studio and you right click your web.config and &lt;strong&gt;Add Config Transformations&lt;/strong&gt; you will end up with the following&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/bbf4cb96-0bd2-4120-a886-47ce9e33512b_image_3276de57-79ac-4584-8185-50f154922ba0.png" width="203" height="321" /&gt;&lt;/p&gt;

&lt;p&gt;This is a major problem for me, as nearly all the places i have worked that use Continuous Delivery or Continuous Integration with ASP.Net websites have used &lt;em&gt;Solution Configurations&lt;/em&gt; for switching between different build environments, not &lt;em&gt;Project Configurations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your website should really only have two build configurations that you use for compilation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Debug &lt;/li&gt;

  &lt;li&gt;Release &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your different environments may be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Local &lt;/li&gt;

  &lt;li&gt;Internal Staging &lt;/li&gt;

  &lt;li&gt;Quality Assurance &lt;/li&gt;

  &lt;li&gt;External Staging &lt;/li&gt;

  &lt;li&gt;Production&lt;/li&gt;

  &lt;li&gt;?? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But all of the above environments will either be compiled in Debug mode or Release mode, so confusing build configurations with environmental configurations feels to me like you are introducing some serious “&lt;a href="http://en.wikipedia.org/wiki/Code_smell"&gt;Code Smell&lt;/a&gt;” into your build setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For some environments you may want to use the same web.config transform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another issue i have with this setup is that it assumes that you have a different transformation for each of your build configurations. What if you use the same environment configurations for a number of your build configurations? Your production-staging environment should probably be the same as your production environment for example – i don't begin to know your requirements, but i do know that mine are not as rigid as this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For some environments you may want to use multiple tiers of web.config transformations applied over the top of each other&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another case where the default usage may not tick all your boxes is when it comes to tiering multiple configurations transformations together. Having the ability to apply transformations in &lt;strong&gt;functionality groups&lt;/strong&gt; instead of &lt;strong&gt;environment groups&lt;/strong&gt; is a very powerful potential usage of transformations.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/76973c23-99a3-40ed-b99b-5a7e60470d25_image_0c543905-b9fd-44c2-bc5f-ca93fce5f35c.png" width="543" height="256" /&gt;&lt;/p&gt;

&lt;h3&gt;So where does this leave us?&lt;/h3&gt;

&lt;p&gt;For me, this put me in the position of wanting badly to find a solution that could give me this level of granularity while still using the transformation tools built into Visual Studio and all the nice convention based functionality that comes with their usage. Up until this point i have been a big fan of abstracting my configs based on environment using something similar to below and swapping the &lt;strong&gt;“\Live\”&lt;/strong&gt; string at build time:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;appSettings &lt;/span&gt;&lt;span style="color: red"&gt;configSource &lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Configs\Live\AppSettings.config&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The major problem with using this technique is that you end up risking having some configurations that are missing certain &lt;em&gt;appSettings&lt;/em&gt; keys and a couple of other annoying niggling issues that you usually only become aware of at the time of deployment (this is a big no-no when using Continuous Integration as the main point of using it is that it removes a lot of the risks of deploying – and this very issue &lt;em&gt;creates &lt;/em&gt;risk). So i was very eager to find a solution that uses config transforms.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/f4ba41c6-e527-4b76-ac0e-50a52e09bb56_image_dcd5ecda-de73-427b-944f-f7e7a378f0f7.png" width="400" height="223" /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“… MSBUILD is a hell of a drug…”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I am a big fan of MSBUILD when writing build scripts, if for no other reason than the fact that &lt;a href="/blog/2010/05/09/automated-site-deployments-with-teamcity-deployment-projects-amp-svn"&gt;Microsoft’s Web Deployment Projects&lt;/a&gt; are basically MSBUILD scripts that integrate well within the Visual Studio IDE.&lt;/p&gt;

&lt;p&gt;Why does this matter? Because I am about to show you a way to use MSBUILD to apply web.config transformations step-by-step, allowing you to apply them with as much fine granularity as you like…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OMFG WTG BBQ R U SERIUZZ!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Short answer: yes&lt;/p&gt;

&lt;h3&gt;The Short Version&lt;/h3&gt;

&lt;p&gt;Applying configuration transformations using MSBUILD is quite easy, all you need is the to have Visual Studio 2010 installed on the machine running your build (in my case this is usually my TeamCity server).&lt;/p&gt;

&lt;p&gt;The bare minimum example for applying a transform is shown below (&lt;strong&gt;do not use this until you have read the rest of this post and become aware of “the bug”)&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UsingTask &lt;/span&gt;&lt;span style="color: red"&gt;TaskName&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformXml&lt;/span&gt;&amp;quot;
                        &lt;span style="color: red"&gt;AssemblyFile&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformWebConfig&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformXml &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\Web.config&lt;/span&gt;&amp;quot;
                  &lt;span style="color: red"&gt;Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\TransformFile.config&lt;/span&gt;&amp;quot;
                  &lt;span style="color: red"&gt;Destination&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\Web.config&lt;/span&gt;&amp;quot;
                  &lt;span style="color: red"&gt;StackTrace&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;My above example kind of explains itself, however just to clarify what this does:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Imports the assembly found at &lt;strong&gt;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll &lt;/strong&gt;and gives it the task name &lt;strong&gt;TransformXml&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;Defines a new target named &lt;strong&gt;TransformWebConfig&lt;/strong&gt; (so that you can call this from somewhere else in your MSBUILD/Web deployment project file, such as in your &lt;strong&gt;AfterBuild&lt;/strong&gt; section). &lt;/li&gt;

  &lt;li&gt;Inside our newly created target, we call &lt;strong&gt;TransformXml &lt;/strong&gt;and pass it the following parameters 

    &lt;ol&gt;
      &lt;li&gt;Our source web.config is located at&lt;strong&gt; C:\Code\MyProject\Web.config&lt;/strong&gt; &lt;/li&gt;

      &lt;li&gt;Our transformation file is located at &lt;strong&gt;C:\Code\MyProject\TransformFile.config&lt;/strong&gt; &lt;/li&gt;

      &lt;li&gt;The end resulting web.config file should be saved to &lt;strong&gt;C:\Code\MyProject\Web.config&lt;/strong&gt; &lt;/li&gt;

      &lt;li&gt;Turn on StackTrace so that in my build log i can review any issues with the transformation such as rules that couldn’t be applied etc (good to have on for review). &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pretty cool eh?&lt;/p&gt;

&lt;p&gt;With the above snippet you can apply as many different transforms as you like in your build scripts by using the command in different ways – even to put into action more advanced configurations such as applying tiered transformations.&lt;/p&gt;

&lt;h3&gt;Thar be Dragons! – Use this instead&lt;/h3&gt;

&lt;p&gt;There is a known issue with the above MSBUILD task though in that it does not close the source web.config file successfully during the application of the transformation causing it to error when reading and writing to the same web.config. &lt;strong&gt;This is very annoying as it causes your build to fail if you use my example above directly&lt;/strong&gt;, because MSBUILD will try and write over the original web.config while it still has it open. To overcome this, i add a simple second step to my build task that copies the web.config to a temporary location and then deletes the file after the transform has taken place.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UsingTask &lt;/span&gt;&lt;span style="color: red"&gt;TaskName&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformXml&lt;/span&gt;&amp;quot;
                        &lt;span style="color: red"&gt;AssemblyFile&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformWebConfig&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OriginalWebConfig &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\Web.config&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TempWebConfig &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\TempWeb.config&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Copy &lt;/span&gt;&lt;span style="color: red"&gt;SourceFiles&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(OriginalWebConfig)&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;DestinationFiles&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(TempWebConfig)&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformXml &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\TempWeb.config&lt;/span&gt;&amp;quot;
                            &lt;span style="color: red"&gt;Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\TransformFile.config&lt;/span&gt;&amp;quot;
                            &lt;span style="color: red"&gt;Destination&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;C:\Code\MyProject\Web.config&lt;/span&gt;&amp;quot;
                            &lt;span style="color: red"&gt;StackTrace&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Delete &lt;/span&gt;&lt;span style="color: red"&gt;Files&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(TempWebConfig)&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;h3&gt;More advanced techniques&lt;/h3&gt;

&lt;p&gt;As i mentioned earlier in this post, i usually prefer to use a more dynamic &lt;em&gt;Solution Configuration&lt;/em&gt; based switching in my Continuous Delivery setups for deployment, and therefore want to be able to have my transforms applied depending on the solution configuration being fired, to allow for more flexibility.&lt;/p&gt;

&lt;p&gt;My usual website project setup includes a folder called &lt;strong&gt;Deployment&lt;/strong&gt; that sits in the root of the site. In this folder i include &lt;a href="/blog/2011/03/27/continuous-integration-ndash-itrsquos-all-about-your-build-projects-ecosystem"&gt;any assets that are used as part of my deployment&lt;/a&gt;. This includes things like a command-line SFTP client, a web.config checker and any configuration files that are used in my build. &lt;strong&gt;I usually have a post build step that deletes this folder so that you don’t find things such as sftp hashes or alternate environment database connection strings finding their way onto your web host’s servers – i highly recommend you follow a similar procedure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/07335338-248c-462a-94d3-7d3881e567e4_image_6f8a824b-5ed1-44ab-9e37-99b405847dda.png" width="287" height="409" /&gt;&lt;/p&gt;

&lt;p&gt;For my example below I base all the properties i send the &lt;strong&gt;TransformXml&lt;/strong&gt; build task shown above on the build configuration parameters and the file paths being used at build time. I also refer to the transform files i have in my &lt;strong&gt;\Deployment\&lt;/strong&gt; folder shown above.&lt;/p&gt;

&lt;p&gt;My example below, does the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Defines a property named WebConfigReplacement and defines it depending on the solution build configuration being used. If building a staging deployment use the staging transform file, if a production deployment use the production config transform file. &lt;/li&gt;

  &lt;li&gt;Copy the web.config file to a temporary location inside my \&lt;strong&gt;Deployment\&lt;/strong&gt; folder &lt;/li&gt;

  &lt;li&gt;Runs the config transform defined in step 1 to the temporary web.config created in step 2 and save it over the top of my web applications web.config &lt;/li&gt;

  &lt;li&gt;Delete the temporary web.config inside my &lt;strong&gt;\Deployment\&lt;/strong&gt; folder. &lt;/li&gt;
&lt;/ol&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;Setup the transformation file to use &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup &lt;/span&gt;&lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;'$(Configuration)|$(Platform)' == 'Deploy - Staging|AnyCPU'&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;WebConfigReplacement&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Staging&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;WebConfigReplacement&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup &lt;/span&gt;&lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;'$(Configuration)|$(Platform)' == 'Deploy - Production|AnyCPU'&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;WebConfigReplacement&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Production&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;WebConfigReplacement&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UsingTask &lt;/span&gt;&lt;span style="color: red"&gt;TaskName&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformXml&lt;/span&gt;&amp;quot;
                        &lt;span style="color: red"&gt;AssemblyFile&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformInputFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;$(OutputPath)\Deployment\Web.Temp.config&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformInputFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;$(OutputPath)\Deployment\Web.$(WebConfigReplacement).config&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformOutputFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;$(OutputPath)\Web.config&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformOutputFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackTraceEnabled&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackTraceEnabled&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OriginalWebConfig &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(OutputPath)\Web.config&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TempWebConfig &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(OutputPath)\Deployment\Web.Temp.config&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;TransformWebConfig&lt;/span&gt;&amp;quot;
                &lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;'$(Configuration)|$(Platform)' == 'Deploy - Production|AnyCPU' Or '$(Configuration)|$(Platform)' == 'Deploy - Staging|AnyCPU'&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;Copy our web.config into a temp folder as the 'TransformXml' task has a file lock bug &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Copy &lt;/span&gt;&lt;span style="color: red"&gt;SourceFiles&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(OriginalWebConfig)&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;DestinationFiles&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(TempWebConfig)&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TransformXml &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(TransformInputFile)&lt;/span&gt;&amp;quot;
                                &lt;span style="color: red"&gt;Transform&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(TransformFile)&lt;/span&gt;&amp;quot;
                                &lt;span style="color: red"&gt;Destination&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(TransformOutputFile)&lt;/span&gt;&amp;quot;
                                &lt;span style="color: red"&gt;StackTrace&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(StackTraceEnabled)&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Delete &lt;/span&gt;&lt;span style="color: red"&gt;Files&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;@(TempWebConfig)&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;&lt;font color="#000000" face="Calibri"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;h3&gt;In closing &lt;/h3&gt;

&lt;p&gt;Hopefully this has given you food-for-thought and got your Continuous Integration juices flowing. Web.config transformations are a very cool feature, so you shouldn’t have to go without just because you are a fan of Continuous Integration – time to come play with all the other kids…&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wukD9ssOC1_3cmTt-hDIyv1-k1w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wukD9ssOC1_3cmTt-hDIyv1-k1w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wukD9ssOC1_3cmTt-hDIyv1-k1w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wukD9ssOC1_3cmTt-hDIyv1-k1w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=-yOk_fripRI:oHpc5m4ICxY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=-yOk_fripRI:oHpc5m4ICxY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=-yOk_fripRI:oHpc5m4ICxY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=-yOk_fripRI:oHpc5m4ICxY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/i7a7u00Ec1Y" height="1" width="1"/&gt;</description><pubDate>9/14/2011 3:02:44 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/09/14/using-custom-webconfig-transformations-in-msbuild</feedburner:origLink></item><item><title>Adding filters to your ELMAH installation</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/JqQWQeZcWEE/adding-filters-to-your-elmah-installation</link><description>&lt;p&gt;One of the most common configurations people use when setting up ELMAH is email exception logging so that you get notified whenever &lt;em&gt;“shit’s goin’ down”&lt;/em&gt; on your site. This leads to a follow on issue that stems from this in that you end up receiving 100’s of emails a couple of times a week as your website gets scanned by evil doers looking for vulnerabilities – but there is a simple and elegant solution.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/698b47c8-f8ca-4e71-9e40-7a3a07e2f18d_image_66c94df5-4558-49e8-99be-14acf646cf45.png" width="250" height="250" /&gt;I really rate &lt;a href="http://code.google.com/p/elmah/"&gt;ELMAH&lt;/a&gt; a one of the greatest contributions made to the ASP.Net community to date. Although it has way more history/lineage that its more contemporary peers such as &lt;a href="http://getglimpse.com/"&gt;Glimpse&lt;/a&gt; or the &lt;a href="http://code.google.com/p/mvc-mini-profiler/"&gt;MiniProfiler&lt;/a&gt;, it definitely hasn’t lost any awesomeness over the years. &lt;/p&gt;  &lt;p&gt;I have been using ELMAH for many years now and am a huge fan, although had never thought to really blog about it until reading a recent blog post from Troy Hunt on “&lt;a href="http://www.troyhunt.com/2011/09/gootkits-futile-attack-on-asafaweb.html"&gt;Gootkit’s futile attack on ASafaWeb&lt;/a&gt;” in which Troy comes unstuck with the first problem that people using ELMAH error emails with ASP.Net MVC often find;&lt;/p&gt;  &lt;p&gt;Below shows my Gmail account “back in the day” before i had solved the bug-bear:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/782b7a52-20db-4cd8-ae03-e794aa94edd1_image_7d559bc9-61fb-4df1-99c8-bc2aeff50393.png" width="450" height="187" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I’m getting spammed by my own website…&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;You end up receiving hundreds of emails a week from script kiddies or botnets scanning your web site for vulnerabilities and the ensuing email storm (9 times out of 10 these requests are usually looking for the &lt;a href="http://wordpress.org/"&gt;WordPress&lt;/a&gt; admin login page @ /wp-login.php – WordPress blogs owners take note: &lt;em&gt;the evil guys are looking for you&lt;/em&gt;).&lt;/p&gt;  &lt;h3&gt;Drowning out the noise&lt;/h3&gt;  &lt;p&gt;There are two different ways to configure ELMAH exception filters at run time, and depending on what you want to achieve they each have their uses. The creator of ELMAH &lt;a href="http://www.raboof.com/"&gt;Aziz Atif&lt;/a&gt; has kindly documented all the ways you can implement these filter exceptions in ELMAH on the project wiki &lt;a href="http://code.google.com/p/elmah/wiki/ErrorFiltering"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Before we start, be aware that all ELMAH filtering requires that you install the &lt;strong&gt;ELMAH filtering module&lt;/strong&gt; if you haven’t already done so, read on.&lt;/p&gt;  &lt;p&gt;To do this you need to:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Add the configuration sections to your web.config&lt;/strong&gt;&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configSections&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;sectionGroup &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;section &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;errorLog&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;requirePermission&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorLogSectionHandler, Elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;section &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;errorFilter&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;requirePermission&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorFilterSectionHandler, Elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;sectionGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configSections&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Add the error filter http module to your website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IIS Classic mode version&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ErrorLog&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorLogModule, Elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ErrorFilter&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorFilterModule, Elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;IIS Integrated mode&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;modules &lt;/span&gt;&lt;span style="color: red"&gt;runAllManagedModulesForAllRequests&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ErrorLog&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorLogModule, Elmah&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;preCondition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;managedHandler&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;ErrorFilter&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Elmah.ErrorFilterModule, Elmah&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;modules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Once you’ve done this you need to look at what solutions will work better for you based on what you really want to achieve, as there are a few different options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I want to filter using &lt;strong&gt;web.config configuration&lt;/strong&gt; to &lt;strong&gt;remove certain exceptions from my ELMAH log&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;I want to filter using &lt;strong&gt;web.config&lt;/strong&gt; &lt;strong&gt;configuration&lt;/strong&gt; to &lt;strong&gt;stop receiving emails for certain exceptions&lt;/strong&gt;. 

    &lt;br /&gt;

    &lt;br /&gt;&lt;strong&gt;OR&lt;/strong&gt; 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;I want to filter using &lt;strong&gt;code&lt;/strong&gt; to &lt;strong&gt;remove certain exceptions based on a complex, granular set of rules.&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;I want to filter using &lt;strong&gt;code&lt;/strong&gt; to &lt;strong&gt;stop receiving emails for certain exceptions based on a complex, granular set of rules.&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe that &lt;strong&gt;you should really be logging all exceptions that occur on your site&lt;/strong&gt; as by filtering out or removing certain exceptions from your ELMAH log you are usually hiding problems in your site or disabling the ability to get a full picture of the health of your website.&lt;/p&gt;

&lt;p&gt;If you have setup the emailing of exceptions this is a slightly different story as while you still want to log all your exceptions &lt;strong&gt;you do not want to get spammed every time someone scans your website for vulnerabilities&lt;/strong&gt; – as experienced by Troy in &lt;a href="http://www.troyhunt.com/2011/09/gootkits-futile-attack-on-asafaweb.html"&gt;his post&lt;/a&gt;. Instead you want to filter out these exceptions so that you only receive notification of issues experienced by everyday visitors to your site. &lt;/p&gt;

&lt;p&gt;Additionally If you have setup ELMAH exception e-mails there are a number of reasons why you don’t want to be spammed by your websites ELMAH installation:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If you have spam filters installed there is a risk that over time your exceptions may start to be blocked by your spam filter, stopping you from having proper visibility over issues on your site. &lt;/li&gt;

  &lt;li&gt;If you are receiving 100’s of exception emails from your website a day there is a good risk that you will become de-sensitized to the real issues hidden within the exception jungle that has become your inbox so that when bad things actually do occur you don’t notice them – nullifying the very reason you have setup ELMAH exception emails in the first place. &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Method #1 – Filtering by web.config &lt;/h3&gt;

&lt;p&gt;My favourite approach to filtering ELMAH exceptions is to use web.config additions to define the filtering rules. This allows you to add new rules without rebuilding your project and with this gives you the flexibility to make changes to your filters “on-the-go” – and as you are probably aware, over time you will come across new types of exception “SPAM”, so having the flexibility to add to these filters simply by firing up SFTP or logging into your webserver is pretty handy.&lt;/p&gt;

&lt;p&gt;The conventions are quite flexible and can be found at the following URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.google.com/p/elmah/wiki/ErrorFiltering#Filtering_Declaratively_via_Configuration"&gt;http://code.google.com/p/elmah/wiki/ErrorFiltering#Filtering_Declaratively_via_Configuration&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;&lt;em&gt;The Basics&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;A basic summary of the ELMAH web.config configuration tags are as follows&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filter Assertions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are many different assertions that you can use to filter exceptions by condition (take a look at the full documentation for more tips), but the ones you’ll use most are shown below. The functionality includes the assertions &lt;em&gt;equal, greater than, less than, regex matching, type matching, custom JScript matching, &lt;/em&gt;and even more awesomly - You can &lt;a href="http://code.google.com/p/elmah/wiki/ErrorFiltering#Writing_Your_Own_Assertion"&gt;write your own assertions &lt;/a&gt;(this is crazily powerful).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;security &lt;/span&gt;&lt;span style="color: red"&gt;allowRemoteAccess&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception equals a filter result &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;equal &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;HttpStatusCode&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;404&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Int32&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception is greater than a filter result &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;greater  &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;HttpStatusCode&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;404&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Int32&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception is less than a filter result &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;lesser &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;HttpStatusCode&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;404&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Int32&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception matches a regular expression against the exception object &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;BaseException.Message&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The file '/[^']+' does not exist&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception matches a certain type of exception &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;is-type &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;BaseException&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.IO.FileNotFoundException&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;

                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;exception matches a custom JScript assertion that matches multiple conditions &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;jscript&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;expression&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                        &amp;lt;![CDATA[
              &lt;/span&gt;&lt;span style="color: gray"&gt;// @assembly mscorlib
              // @assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
              // @import System.IO
              // @import System.Web

              HttpStatusCode == 404
              || BaseException instanceof FileNotFoundException 
              || BaseException instanceof HttpRequestValidationException
              /* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */
              || Context.Request.UserAgent.match(/crawler/i)                      
              || Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only
              &lt;/span&gt;&lt;span style="color: blue"&gt;]]&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;expression&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;jscript&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Filter selectors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you have figured out all the assertions that apply to the exceptions you want to filter out, you can join them all together using filter selectors to enable the use of more than one filter at a time (which will nearly always be the case). You can tier your filters selectors together in a parent/child relationship to even more expressively state your intentions:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;security &lt;/span&gt;&lt;span style="color: red"&gt;allowRemoteAccess&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;insert multiple filter tests for alternate assertions &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;insert multiple filter tests for inclusive assertions &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;em&gt;Actually applying Filters in the web.config&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Now that I've shown you the conventions used by ELMAH to express exception filters lets take a look at some examples. It is important to note that up until this point &lt;strong&gt;we have only been talking about writing filters to remove them from ELMAHs log, not to simply not email you about them&lt;/strong&gt; – this is something i get to below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regex exception matching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Filter exceptions by Type (in this case &lt;em&gt;System.Web.HttpException)&lt;/em&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;security &lt;/span&gt;&lt;span style="color: red"&gt;allowRemoteAccess&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Exception&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Web.HttpException&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The controller for path '/[^']+' was not found or does not implement IController.&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Exception&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Web.HttpException&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Web.HttpException: A public action method '[^']+' was not found on controller '[^']+'.&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Filter exceptions by Exception Message body:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;security &lt;/span&gt;&lt;span style="color: red"&gt;allowRemoteAccess&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;BaseException.Message&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The file '/[^']+' does not exist&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;BaseException.Message&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The controller for path '/[^']+' was not found or does not implement IController.&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Filtering Exceptions from Email only&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The great part about all of these filtering assertions are they can be combined with the type of filter being used by ELMAH to &lt;strong&gt;filter only the Exceptions being emailed to us&lt;/strong&gt; – &lt;em&gt;which is the very point of this post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Only specifically target errors being &lt;strong&gt;emailed&lt;/strong&gt; so that we don’t receive them&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;security &lt;/span&gt;&lt;span style="color: red"&gt;allowRemoteAccess&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;BaseException.Message&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The file '/[^']+' does not exist&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;FilterSourceType.Name&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;mail&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Exception&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Web.HttpException&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;The controller for path '/[^']+' was not found or does not implement IController.&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;regex &lt;/span&gt;&lt;span style="color: red"&gt;binding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;FilterSourceType.Name&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;pattern&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;mail&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;and&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;or&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;test&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;errorFilter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;elmah&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;h3&gt;Method #2 – Filtering by code&lt;/h3&gt;

&lt;p&gt;The other approach to creating ELMAH filters is to use code, either in your own http module or inside your Global.asax.&lt;/p&gt;

&lt;p&gt;This obviously requires more work, but also gives you a lot more of a fine grained control over your exception logging. &lt;strong&gt;Again, there is a solution for just plain Exception filtering to ‘not log the exception’ as well as &lt;em&gt;Email Exception filtering&lt;/em&gt; to not send an email for a certain type of exception&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When ELMAH raises an exception, it raises the &lt;em&gt;Filtering&lt;/em&gt; event to see if any listeners want to dismiss it. By default it looks for methods in your &lt;strong&gt;Global.asax&lt;/strong&gt; that match a certain convention and executes them as listeners. There are two different method names it looks for, each for the two functionalities we talked about in the previous paragraph: Error Filtering and Email Error Filtering.&lt;/p&gt;

&lt;p&gt;By referencing the ELMAH Binary in your Global.asax and inserting the following two methods you can then add your own logic to enable you to interact with the exception at runtime, either to extend its functionality or to dismiss the exception from ELMAH before it gets &lt;strong&gt;logged&lt;/strong&gt; or &lt;strong&gt;emailed&lt;/strong&gt; (depending on which method you add your logic to). &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;ErrorLog_Filtering(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;ExceptionFilterEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: green"&gt;// don't log HttpRequestValidationException's
    &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(e.Exception.GetBaseException() &lt;span style="color: blue"&gt;is &lt;/span&gt;&lt;span style="color: #2b91af"&gt;HttpRequestValidationException&lt;/span&gt;)
        e.Dismiss();
}
&lt;span style="color: blue"&gt;void &lt;/span&gt;ErrorMail_Filtering(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;ExceptionFilterEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: green"&gt;// Don't email me about files not being found
    &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(e.Exception.GetBaseException() &lt;span style="color: blue"&gt;is &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FileNotFoundException&lt;/span&gt;)
        e.Dismiss();
}&lt;/pre&gt;

&lt;p&gt;As you can see, with these code snippets you can have some pretty powerful control over what ELMAH does with your exceptions. This should conjure up a number of scenarios you may want to accomplish – Maybe you want to disable error emails when a certain condition is met (maybe an app setting), maybe you want to not log exceptions if they are a certain type. What you do is not important, but knowing the power and flexibility you have at hand can only be a good thing.&lt;/p&gt;

&lt;h3&gt;Further ideas&lt;/h3&gt;

&lt;p&gt;Using code you can plug into the Elmah exception events when they happen allowing you to really extend the functionality to get more value.&lt;/p&gt;

&lt;p&gt;Some cool ideas i have come across:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Alter the email being sent by ELMAH to change its priority and subject depending on conditions 
    &lt;br /&gt;&lt;a href="http://scottonwriting.net/sowblog/archive/2011/01/06/customizing-elmah-s-error-emails.aspx"&gt;http://scottonwriting.net/sowblog/archive/2011/01/06/customizing-elmah-s-error-emails.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;Plugging into ASP.Net MVC 3 to use ELMAH as well as the ASP.net MVC exception handling 
    &lt;br /&gt;&lt;a title="http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute/779961#779961" href="http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute/779961#779961"&gt;http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute/779961#779961&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;Manually logging to ELMAH using error Signalling 
    &lt;br /&gt;&lt;a href="http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Error_Signaling"&gt;http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Error_Signaling&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WqNTkHVvvInlzzKKEuy6am0rYNk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WqNTkHVvvInlzzKKEuy6am0rYNk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WqNTkHVvvInlzzKKEuy6am0rYNk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WqNTkHVvvInlzzKKEuy6am0rYNk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=NIO2eOWLFNg:CW20NX3iRK4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=NIO2eOWLFNg:CW20NX3iRK4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=NIO2eOWLFNg:CW20NX3iRK4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=NIO2eOWLFNg:CW20NX3iRK4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/JqQWQeZcWEE" height="1" width="1"/&gt;</description><pubDate>9/20/2011 10:49:24 PM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/09/20/adding-filters-to-your-elmah-installation</feedburner:origLink></item><item><title>What good Web Developers should know about sending E-mail</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/vFh9F-W22HU/what-all-good-web-developers-should-know-about-sending-email</link><description>&lt;p&gt;Nearly all websites these days send email and because of this the majority of developers assume that they “know how to send email from a website”. They continue under this assumption until they have a site or server of their get black listed by a Spam blacklist. Then they are forced to scratch their heads to try and figure out why this happened. Before you hit send on that email requesting to be removed from that Spam blacklist, let’s recap what you should be doing to make sure it doesn’t happen again.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 5px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/a4ff1272-94fe-4cec-b339-0b0bfdc0628b_image_dc5bf7c6-d4d1-40b1-9c88-b3f0be971251.png" width="250" height="284" /&gt;So you’re developing a website, and you or your client wants this website to send an email. &lt;/p&gt;  &lt;p&gt;Maybe it’s to visitors who sign up for your service, or maybe you have a “Send to a friend” service that allows your visitors to spread the word about your content or service. &lt;/p&gt;  &lt;p&gt;Maybe you just want to send them a notification every time one of their friends virtually &lt;a href="http://en.wikipedia.org/wiki/Facebook_features#Poke"&gt;pokes&lt;/a&gt; them from your soon-to-be social network project (watch out for those &lt;a href="http://en.wikipedia.org/wiki/Winklevoss_twins"&gt;Winklevoss twins&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;No matter the usage, these added functionalities to your website all depend on E-mail and the &lt;em&gt;assumption&lt;/em&gt; that these emails will get to their intended recipient. &lt;/p&gt;  &lt;p&gt;Sadly, decades of abuse of the very E-mail services you are trying to deliver your message over by nefarious characters around the world has lead to us all being in a heightened state of &lt;a href="http://en.wikipedia.org/wiki/DEFCON"&gt;Email DefCon Level 1&lt;/a&gt;. This means that at nearly every email gateway server around the world, system administrators and network engineers are working hard to make sure that Spam (or perceived Spam) doesn’t get through to their users’ mailboxes. &lt;/p&gt;  &lt;p&gt;This means that &lt;em&gt;you and your website&lt;/em&gt; need to be careful to not make the Uncle Sam’s of the network administration world go nuclear on your message.&lt;/p&gt;  &lt;h3&gt;A look at ways Spam filters can work&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;NOTE: Every different Spam filter on the planet does things a little differently (otherwise they’d have nothing to compete over), and I am not making blanket statements that this is how they all work.&amp;#160; More simply, these are some of the things that Spam filters look at so that, in sharing them &lt;em&gt;you as a developer&lt;/em&gt; can be more wary of them in your next project.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In order to make it easier to understand what I am about to explain I have going to create a virtual email for us to talk about. This example email’s basic information is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Sender: JohnDoe@virtualcorp.com      &lt;br /&gt;Recipient: MarthaNoName@centuryco.com       &lt;br /&gt;Sending Servers IP: 202.202.202.1       &lt;br /&gt;Subject: Welcome to Widgets.com&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Most Spam filters work under the pretence of incoming mail being given a score based on its &lt;em&gt;risk&lt;/em&gt; of being Spam. They will do a number of checks and give your message a score – if this score is above/below the configured level for flagging your message as Spam &lt;em&gt;or not&lt;/em&gt; it will then either let your email through to the recipients mailbox or reject it (depending on the Spam filter software being used, the response may be that your mail simply gets placed in a mailbox folder for review; &lt;em&gt;think of GMAILs [Spam] folder&lt;/em&gt;).&lt;/p&gt;  &lt;p&gt;Lets take a look at the lifecycle and some of the checks that occur, and then take a look at ways you can make sure your message makes the cut.&lt;/p&gt;  &lt;h3&gt;&lt;em&gt;Step 1 – Your Email is received&lt;/em&gt;&lt;/h3&gt;  &lt;p&gt;The first thing the Spam filters usually do is take note of the &lt;strong&gt;domain name of the email’s sender&lt;/strong&gt; (in our example email - virtualcorp.com) and the &lt;strong&gt;IP address of the sending server &lt;/strong&gt;(in our example - 202.202.202.1) that it was received from as well as the &lt;strong&gt;domain name your server sends in its &lt;a href="http://the-welters.com/professional/smtp.html"&gt;HELO command&lt;/a&gt;&lt;/strong&gt; at time of connection.&lt;/p&gt;  &lt;h3&gt;&lt;em&gt;Step 2 – Email interrogation&lt;/em&gt;&lt;/h3&gt;  &lt;p&gt;Now that a number of properties of your email have been noted, the Spam filter will then run a number of checks against your email. In the case of the bad guys there a usually a whole heap of things that happen outside of the list i am about to explain; such as heuristics on the email’s body content. As we are sending normal e-mail all we should worry about are the flags that could cause a &lt;em&gt;false positive&lt;/em&gt; to occur.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;DNS Background Check&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The Spam filter will probably then do a &lt;a href="http://en.wikipedia.org/wiki/Reverse_DNS_lookup"&gt;reverse DNS lookup&lt;/a&gt; to see if the &lt;strong&gt;IP address of the sending server&lt;/strong&gt; resolves to the &lt;strong&gt;domain name that is used when initiating connection&lt;/strong&gt; (The HELO message) or the &lt;strong&gt;domain name of the email sender&lt;/strong&gt; (in our example - &lt;strong&gt;virtualcorp.com&lt;/strong&gt;). &lt;/p&gt;  &lt;p&gt;Is this the reverse DNS hostname used in the server’s connection HELO message? Is this reverse DNS hostname included in the SPF records for the sending domains DNS? (shown later in this post). Is this server even connected to JohnDoe@virtualcorp.com?&lt;/p&gt;  &lt;p&gt;It may then look up the &lt;a href="http://en.wikipedia.org/wiki/Domain_Name_System#DNS_resource_records"&gt;Forward DNS entries&lt;/a&gt; for the domain name of the email’s sender (again this is &lt;strong&gt;virtualcorp.com)&lt;/strong&gt; and look to see if the A record for that domain points to the IP address of the sending server or an IP in the same subnet block (i.e is the sending server actually the webserver that hosts the site or connected to this site in any way?). &lt;/p&gt;  &lt;p&gt;All of these will be added to the email’s &lt;em&gt;risk score&lt;/em&gt;. Some filters rate some checks higher than others.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Reverse DNS How-to&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;If you want to look up the reverse DNS entry for the your server’s IP address the simplest way is to visit a site like &lt;a href="http://remote.12dt.com"&gt;this one&lt;/a&gt; and enter your servers IP address.&lt;/p&gt;  &lt;p&gt;Alternatively, open a command prompt (if using windows) or a terminal (if using a Unix flavour) and type the following:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Nslookup&lt;/strong&gt; [IP ADDRESS YOU WANT TO LOOKUP] &lt;em&gt;Hit Enter&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;The result when looking up the reverse DNS entry for Google’s DNS server 8.8.8.8&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/6946a021-4755-4b03-95c4-73edd412984a_image_079031f1-36d7-4fec-89ee-6666d7958acb.png" width="565" height="283" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;DNS SPF Record Check&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Another common approach a Spam filter will take is to look up the &lt;a href="http://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF record&lt;/a&gt; and/or the &lt;a href="http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx"&gt;Sender ID&lt;/a&gt; SPF record for the domain name you have as sender in your email message (again this is &lt;strong&gt;virtualcorp.com&lt;/strong&gt;). &lt;/p&gt;  &lt;p&gt;DNS SPF records define a list of servers that are allowed to send email on behalf of a domain name. They are an important way of defining servers that are not normally associated with your domain name to be recognised as being verified – if you are using a server that is shared across your webhosting ISP’s other customers, this allows you to white-list this server as being related to your website’s domain (a connection that normally might not be a clear as it should be).&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Example&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The following SPF record for &lt;strong&gt;example.com&lt;/strong&gt; indicates that only one server can send on behalf of &lt;strong&gt;example.com&lt;/strong&gt; and that is the server &lt;strong&gt;mail.example.com;&lt;/strong&gt;&lt;/p&gt;  &lt;pre class="code"&gt;example.com.  TXT  &amp;quot;v=spf1 a:mail.example.com -all&amp;quot;&lt;/pre&gt;

&lt;h3&gt;What does this mean for &lt;u&gt;us web developers&lt;/u&gt;?&lt;/h3&gt;

&lt;p&gt;You may being thinking at this point:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Who cares about DNS entries and all this other bumf? &lt;/p&gt;

  &lt;p&gt;I &lt;u&gt;can&lt;/u&gt; send email as another persons email address – I've done it before! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are sending email from your website, then you &lt;u&gt;should care&lt;/u&gt; – not just because your message might not get through this once, but because a lot of Spam filters keep a score for sending servers and may either report back to a blacklist if they constantly see bad mail coming from it or may just reject all mail from you in the future. When you are sending email to a huge network of email servers (such as Gmail or Hotmail), them remembering you as sending bad mail is not a good thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This means that by not playing by the rules, you can actually over time get your server blacklisted.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Additionally, just because it hasn’t happened yet, doesn’t mean it won’t happen one day.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;So what can be done to try and allow our E-mails get through?&lt;/h3&gt;

&lt;p&gt;After all this information, it might not be 100% clear what you can do to make sure you E-mail gets to its intended recipients and that you don’t set off any Spam false positives in the process. The list is quite small, and simple and usually if you stick to a few simple rules you should be fine.&lt;/p&gt;

&lt;p&gt;Lets take a look at how you can use this information to your benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never send email from a sender address on a domain you do not control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are building a website that sends email, try to avoid sending &lt;u&gt;&lt;em&gt;as&lt;/em&gt;&lt;/u&gt; another user. &lt;/p&gt;

&lt;p&gt;This means if you are building a “send-to-a-friend” form, or a “send this user an email” functionality always try and send &lt;strong&gt;from an email address on your domain&lt;/strong&gt;, not as the &lt;strong&gt;user’s email address&lt;/strong&gt; – you can add the user you are &lt;em&gt;sending-on-behalf-of&lt;/em&gt; as the “&lt;em&gt;reply-to&lt;/em&gt;” email address, but always send from a sender email address that lives on a domain you control.&lt;/p&gt;

&lt;p&gt;If your websites domain name is &lt;strong&gt;“widgetsareus.com”&lt;/strong&gt; make sure you send from an email address such as &lt;strong&gt;“website@widgetsareus.com” &lt;/strong&gt;&lt;u&gt;not&lt;/u&gt; &lt;strong&gt;“ladiesman69@hotmail.com”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure that you have your DNS ducks are in a row&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are sending from an email address on a domain that is hosted on another server (such as using a shared SMTP server from your webhost), get your DNS in order. If you are not in control of your site’s DNS make sure that whoever &lt;strong&gt;is&lt;/strong&gt; knows about the following;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The ISP that hosts your server sets up a valid reverse DNS entry for your server’s external facing IP address that it points at a hostname that is a sub-domain of the domain name you wish to send as if possible. If you are using a shared SMTP server this is usually not possible as the server will be sending email for many different domain names not just yours –&lt;strong&gt; in this case SPF&lt;/strong&gt; &lt;strong&gt;records are even more important&lt;/strong&gt;. 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Setup an SPF and Sender-ID SPF record for your domain name that includes the external facing IP address or hostname of your mail server. If you need some help, give the following sites a visit: 
    &lt;ol&gt;
      &lt;li&gt;SPF Record Documentation 
        &lt;br /&gt;&lt;a href="http://www.openspf.org/SPF_Record_Syntax"&gt;http://www.openspf.org/SPF_Record_Syntax&lt;/a&gt; &lt;/li&gt;

      &lt;li&gt;Sender ID Setup Wizard 
        &lt;br /&gt;&lt;a href="http://www.microsoft.com/mscorp/safety/content/technologies/senderid/wizard/"&gt;http://www.microsoft.com/mscorp/safety/content/technologies/senderid/wizard/&lt;/a&gt; &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Verify your SMTP server is configured correctly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you control the SMTP server that is sending your mail make sure it is configured to give its reverse DNS hostname in its HELO connection greeting from its reverse DNS hostname or the domain name that you are sending from.&lt;/p&gt;

&lt;p&gt;Also make sure that &lt;a href="http://en.wikipedia.org/wiki/Open_mail_relay"&gt;relaying&lt;/a&gt; is turned off – &lt;strong&gt;THIS IS PRETTY CRITICAL&lt;/strong&gt;&lt;strong&gt;. &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To check if you have this turned on, check out an open relaying tool such as the one of the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.mxtoolbox.com/diagnostic.aspx"&gt;http://www.mxtoolbox.com/diagnostic.aspx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.checkor.com/"&gt;http://www.checkor.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify that your SMTP server is not on any blacklists&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are hundreds of Spam blacklists, but MXToolbox has a great tool for checking your servers IP address @ &lt;a href="http://www.mxtoolbox.com/blacklists.aspx"&gt;http://www.mxtoolbox.com/blacklists.aspx&lt;/a&gt;. If you find yourself on any of the above, double check that you have configured your server correctly and politely email the administrators of the blacklist and request to have your server’s IP address removed.&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;Sending E-mail from your website is not a complicated task (as your probably already know). Trying to assure that your email messages get to their recipients is not too hard as long as you stick to a couple of simple rules. &lt;/p&gt;

&lt;p&gt;Hopefully the list above, will allow you to get back to doing what you do best – rocking the web.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have written a follow up post on using DKIM and Domain Keys to “sign your email” when you want to take this a step further.&lt;/p&gt;

  &lt;p&gt;Check it out:
    &lt;br /&gt; &lt;a href="/blog/2011/11/16/when-you-really-need-your-email-delivered-ndash-signing-your-mail-using-domain-keysdkim"&gt;When you really need E-mail delivered – Signing your mail using DKIM&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wR0jMfdXapWka6MSUo5UdkdrVx4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wR0jMfdXapWka6MSUo5UdkdrVx4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wR0jMfdXapWka6MSUo5UdkdrVx4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wR0jMfdXapWka6MSUo5UdkdrVx4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eqBakTzG5ac:nPkvG0rWQtQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eqBakTzG5ac:nPkvG0rWQtQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eqBakTzG5ac:nPkvG0rWQtQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=eqBakTzG5ac:nPkvG0rWQtQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/vFh9F-W22HU" height="1" width="1"/&gt;</description><pubDate>9/27/2011 1:29:59 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/09/27/what-all-good-web-developers-should-know-about-sending-email</feedburner:origLink></item><item><title>Getting your Windows Phone 7 Device Syncing after upgrading to Mango on a Guest PC</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/Q5tZkYDEWDI/getting-your-windows-phone-7-phone-synching-after-upgrading-to-mango-on-a-guest-pc</link><description>&lt;p&gt;During the big Mango update rush over the last 3 weeks i joined the rest of the Windows Phone 7 Development community and excitedly upgraded my phone from Windows Phone 7 Mango Beta to the real thing. I was so eager to upgrade &lt;em&gt;right now&lt;/em&gt; that I did so on my work PC where I connect my phone as a &lt;em&gt;Guest.&lt;/em&gt; This happily got me up and running (definite thanks to the WP7 team for doing such a great job of the upgrade experience). My troubles only began when i tried to synch my phone at home a couple of days later. Hopefully i can save a few of you the time i spent looking into this.&lt;/p&gt;  &lt;p&gt;The first thing that greeted me upon plugging in my newly upgraded Windows Phone 7 Mango device at home was the following screen;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“…Connection Error&lt;/p&gt;    &lt;p&gt;Can’t connect to your phone. Disconnect it, restart it, then try connecting again…”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/b3fd5dc8-2ec0-406a-ac0c-e1e1c25c783a_image_3505a71d-6b1f-4ec3-80ea-3a1ae3c6c8d0.png" width="414" height="127" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Yay, my phone is broken, how exciting…&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I can tell you that the above error message made me slightly worried. I have had my Samsung Omnia 7 for just on a year now and it has served my development journey into the Windows Phone 7 world well, however the last few months have given me some small niggling worries as the phone has started to show the signs of a phone that has been bashed on a meeting room table a couple of times a day as it followed me along in “a day in the life of Doug”. A few weeks ago it started thinking it was always critically low on battery, and this certificate issue appeared to be another fun little adventure related to a potential USB connector dyeing.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Luckily for me this was not my issue.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Instead, the above occurs when your phone changes its &lt;em&gt;identifier&lt;/em&gt; and therefore its Zune personal security certificate is no longer valid. This issue can be caused for a million and one other reasons, but the issue itself is documented on the following MSDN article;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/2468307"&gt;http://support.microsoft.com/kb/2468307&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Steps to Resolve – “i don’t care, i just want my phone back”&lt;/h3&gt;  &lt;p&gt;The first way to fix this is here more for the kind folk who’ve probably landed here from a Google search. If you just wanted it fixed and don’t care how it is done, follow these steps;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Connect Windows Phone 7 phone to your computer using your USB cable. &lt;/li&gt;    &lt;li&gt;Open the Zune software. &lt;/li&gt;    &lt;li&gt;Revel in the awesomeness that is the connection error we are talking about above. &lt;/li&gt;    &lt;li&gt;Click &lt;b&gt;Settings&lt;/b&gt;, located in the upper-right corner of the screen.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/554f90d8-96c3-4262-8c8a-1968eba960ed_image_9bae3183-9eb7-40dd-a1e7-ec89ac2c9205.png" width="507" height="93" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Click &lt;b&gt;Phone&lt;/b&gt;, located in the upper-left corner of the screen.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/9c10d0a0-4b2f-4d52-9b0f-292ed6e8411b_image_699e2efa-2df0-45ed-83a2-936bf69c14d1.png" width="508" height="117" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Click &lt;b&gt;Sync options&lt;/b&gt;, located in the list at the left.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/727ceeaa-986b-46c3-8261-b89a2e23c2f9_image_7e429882-5a2f-4564-9361-c57612004f99.png" width="242" height="363" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Click the &lt;b&gt;Forget this phone&lt;/b&gt; button. This is located underneath &lt;strong&gt;Device options &lt;/strong&gt;in the middle of the page.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/2c19102c-4be9-43fc-acab-57d091d56240_image_14c8ead7-3213-44b2-9848-6efdf1599184.png" width="508" height="201" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;You’re done!      &lt;br /&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;Steps to Resolve – “I’m a techie and want to learn something along the way”&lt;/h3&gt;  &lt;p&gt;If however you want to solve the problem while learning a little bit about Zune’s relationship with your phone, then maybe follow this guide instead. The steps below were my initial solution, and I know that many of you out there are, like me, interested in the finer details of why this error is caused, and technically how “Forget this phone” works.&lt;/p&gt;  &lt;p&gt;Communication between your Windows Phone 7 device and your PC is encrypted in transit over USB comms using a personal certificate that is installed on your PC by Zune. There is a new personal certificate for each Zune device you have, be it an actual Zune media device or a Windows Phone 7 phone.&lt;/p&gt;  &lt;p&gt;The error that you are experiencing above is caused by one of the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Your phone’s certificate changing, maybe from an Operating System Update. &lt;/li&gt;    &lt;li&gt;Your phone being restored from a backup firmware. &lt;/li&gt;    &lt;li&gt;The local certificate becoming corrupted on your PC. &lt;/li&gt;    &lt;li&gt;Using security certificate software that modifies your personal certificate store (such as provided by Spanish Government for their &lt;a href="http://www.usatudni.es/dnie/"&gt;Electronic National Identity program&lt;/a&gt;). Usually if this is the case your need to uninstall the software while you follow the steps below to reset the personal certificate for your device – usually your can reinstall the software afterwards without any issue. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All of these are rectified pretty simply by Zune when you simply delete the local copy of the personal certificate for your device. This is what the “Forget this Phone” feature does, as it causes Zune to create the certificate again from your device.&lt;/p&gt;  &lt;p&gt;Steps to “reset” the certificate that Zune uses to communicate with your Windows Phone 7 handset:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;If currently running, close &lt;strong&gt;Zune&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Make sure you are logged into an account with &lt;strong&gt;Local Administrator access.&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Click on &lt;b&gt;Start&lt;/b&gt;, type &lt;b&gt;certmgr.msc&lt;/b&gt; and press &lt;strong&gt;Enter&lt;/strong&gt; to open Certificate Manager.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/4f1a5fc9-f335-477a-aa58-a6eed9d672ee_image_5e4b40b8-6e24-4d41-960c-ea16c474f632.png" width="411" height="85" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Once Certificate Manager has opened, open the &lt;b&gt;Personal&lt;/b&gt; folder in the left column, and then the &lt;b&gt;Certificates&lt;/b&gt; folder, on the right.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/3c2a6ae1-391f-4b5a-ad3b-84a866aa308e_image_d9460464-a885-4533-b11c-049cd45d0454.png" width="415" height="323" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Now look for a certificate that reads &amp;quot;&lt;strong&gt;zune-tuner://windowsphone/...&amp;quot;.        &lt;br /&gt;&lt;/strong&gt;(if you have more than one windows phone, there will be multiple. Don’t be afraid to delete them all.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/6bea8332-2ce7-4f09-9d7a-1cb37ba740c4_image_4fdcf5fe-24b1-45be-b90e-f3f015e4e85c.png" width="415" height="308" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Right-click each certificate in the list that matches &lt;strong&gt;“zune-tuner://windowsphone/”&lt;/strong&gt;&amp;#160; and click &lt;b&gt;Delete, &lt;/b&gt;and then click &lt;b&gt;Yes&lt;/b&gt;.       &lt;br /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/42a8a5e2-8163-41ea-9140-fa2ce6c8835f_image_876e0a44-834e-4d36-8f14-68e5c9839b49.png" width="415" height="310" /&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Close the certificate manager &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;Open Zune and connect your Windows Phone 7 phone – you should be back up and synching again!&lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2U5eB60B3ABcmRGmYJEvc6nwrps/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2U5eB60B3ABcmRGmYJEvc6nwrps/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2U5eB60B3ABcmRGmYJEvc6nwrps/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2U5eB60B3ABcmRGmYJEvc6nwrps/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=vHtnXZc2jvs:rHJChU9LlQw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=vHtnXZc2jvs:rHJChU9LlQw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=vHtnXZc2jvs:rHJChU9LlQw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=vHtnXZc2jvs:rHJChU9LlQw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/Q5tZkYDEWDI" height="1" width="1"/&gt;</description><pubDate>10/16/2011 10:35:04 PM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/10/16/getting-your-windows-phone-7-phone-synching-after-upgrading-to-mango-on-a-guest-pc</feedburner:origLink></item><item><title>Xbox Kinect Hub Remake - An Introduction To Natural User Interfaces</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/EYOUTUqPn3o/remaking-the-xbox-kinect-hub--an-introduction-to-new-user-interfaces</link><description>&lt;p&gt;I first started playing around with my Kinect at home just to get a feel for what was involved in working with the SDK – I must say that I, like many of you, was amazed, and still am, at how awesomely simple and beautifully designed the API’s in the Kinect NUI framework are. A lot of people have written little Kinect demo’s showing how to create buttons and detect hand location, but I thought I’d try something different. So I set out to mimic some of the Xbox Live's interface elements in WPF.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/624cb0e4-31c4-4351-badd-9b384fee8a6f_image_e4b6866b-beb5-4a14-85de-8c348e6bf7b9.png" width="350" height="210" /&gt;&lt;/p&gt;  &lt;p&gt;I must admit this post might be a little late in it’s timing – most people where blogging about the &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/"&gt;Kinect SDK&lt;/a&gt; at the very start of this year, and while I was part of that throng of developers excitedly crawling all over the SDK like a pack of red-cordial infected pre-school children who’ve just discovered a secret stash of unattended Space Hoppers, I simply haven't had the time I'd like to write about it. I cannot contain that silence any longer.&lt;/p&gt;  &lt;h3&gt;Game Plan&lt;/h3&gt;  &lt;p&gt;Before you set off on any little learning adventure you usually want to have a set goal in mind to make your learning experience more driven – for me this was accomplishing something different to a lot of the tutorials out there and that was to create a unified interface that closely matched the Xbox Kinect Hub that you use to navigate around your Xbox with.&lt;/p&gt;  &lt;p&gt;You can find a walkthrough of the interface I’m talking about below.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:abc6784b-f61c-4269-9f34-4b8b035d9cff" class="wlWriterSmartContent"&gt;   &lt;div&gt;&lt;embed height="252" type="application/x-shockwave-flash" width="448" src="http://www.youtube.com/v/VdGlAt3OIfA?hl=en&amp;amp;hd=1" /&gt;&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;But basically, I want something similar to the Kinect Hub (screen shots below).&lt;/p&gt;  &lt;p&gt;Primarily I want to create an interface that has a tile based layout and allows you to “press” the buttons with your hand. This would then allow me to create applications that allow you to “navigate” around a series of pages and view “assets” – whether they be videos or images. The navigation sections won’t be covered in this post, but i plan on doing a number of other posts covering these functionalities.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://www.diaryofaninja.com/asset/blogimages/b77a56ba-0673-41a3-8291-6f38f1c56fc8_clip_image003_fb53eab4-5ee1-46b4-9bc2-ab08e0ef512b.jpg" width="450" height="247" /&gt;&lt;/p&gt;  &lt;p&gt;I also want a “hand” cursor that has a timer based “ring” that is used to “press” the buttons similar to the screen below:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/c0cf291b-cff4-4ca6-b80f-75f8a7d38fb7_image_0b52a170-7b0b-45bb-a124-52a8753b3ce3.png" width="450" height="210" /&gt;&lt;/p&gt;  &lt;h3&gt;Getting started&lt;/h3&gt;  &lt;p&gt;Before we start out on our building adventure, you’ll need to grab the necessary tools for the job. &lt;/p&gt;  &lt;p&gt;You’ll need the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;a Kinect for Xbox 360 Sensor &lt;/li&gt;    &lt;li&gt;Visual Studio Express of higher &lt;/li&gt;    &lt;li&gt;.Net Framework 4.0 &lt;/li&gt;    &lt;li&gt;Kinect SDK - &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/"&gt;http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Once you've got all this installed and setup i recommend you do a quick restart (I've found on both my work and home pc, that there are usually issues using the SDK before you first restart).&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;WARNING, DON’T DO THIS AT HOME KIDS&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;I am a web developer by trade. I do not have much experience with WPF/Windows Forms. Therefore, any code you see in this post that you want to sip sherry and scoff at while going about your day job bringing a new accounting package to the world (I kid, I kid…) will probably be perfectly warranted and I’d love to hear from you on ways you’d do things differently or where I’ve gone wrong. Additionally, my code has been simplified to make it shorter to fit with the format of this post. This is my journey into the world of the Kinect SDK, be gentle :-)&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;API Design - A Work Of Art&lt;/h3&gt;  &lt;p&gt;Before we make a start on the project i have to give a quick shout out to the &lt;a href="https://twitter.com/KinectSDKTeam"&gt;Kinect SDK team&lt;/a&gt;. They have done a stunning job on the design of the SDK and the API’s that come with it. You just have to take a look at the skeleton tracking section of the API to see how elegant the API allows your code to become:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;SkeletonFrameReady(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;SkeletonFrameReadyEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;SkeletonFrame &lt;/span&gt;skeletonSet = e.SkeletonFrame;

    &lt;span style="color: #2b91af"&gt;SkeletonData &lt;/span&gt;firstPerson = (&lt;span style="color: blue"&gt;from &lt;/span&gt;s &lt;span style="color: blue"&gt;in &lt;/span&gt;skeletonSet.Skeletons
                                &lt;span style="color: blue"&gt;where &lt;/span&gt;s.TrackingState == &lt;span style="color: #2b91af"&gt;SkeletonTrackingState&lt;/span&gt;.Tracked
                                &lt;span style="color: blue"&gt;orderby &lt;/span&gt;s.UserIndex &lt;span style="color: blue"&gt;descending
                                select &lt;/span&gt;s).FirstOrDefault();
}&lt;/pre&gt;

&lt;p&gt;Is that just beautiful or what? In my example above you get handed a list of &lt;b&gt;IEnumerable&lt;/b&gt;&lt;b&gt;&amp;lt;SkeltonData&amp;gt;&lt;/b&gt; and you’re off.&lt;/p&gt;

&lt;p&gt;Follow this up with amazing little gems such as the access provided to all the major body joints of a skeleton and you start to get this sudden rush that you only get when first start hacking around with something awesome early in your career – remember the time you &lt;a href="http://en.wikipedia.org/wiki/Grok"&gt;grok’d&lt;/a&gt; your first programming language and wanted to take over the world with &lt;a href="http://en.wikipedia.org/wiki/Logo_(programming_language)"&gt;LOGO&lt;/a&gt; controlled green turtles? This will bring back those glory days.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Joint &lt;/span&gt;rightHand = jointsCollection[&lt;span style="color: #2b91af"&gt;JointID&lt;/span&gt;.HandRight];
&lt;span style="color: #2b91af"&gt;Joint &lt;/span&gt;leftHand = jointsCollection[&lt;span style="color: #2b91af"&gt;JointID&lt;/span&gt;.HandLeft];&lt;/pre&gt;

&lt;h3&gt;On with the show&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The first part of my project involved just basically setting up a new WPF project. &lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/e23663fb-d48c-4e7b-9bfd-04a72dff11f6_image_1333b7b0-bc43-4163-8fa9-69d639dd75c3.png" width="450" height="311" /&gt;&lt;/p&gt;

&lt;p&gt;We are ready to get going, and the first thing i want to do is implement the Xbox Kinect Hub “hand”.&lt;/p&gt;

&lt;p&gt;This is an interesting part of the project, as to solve it I’m going to hack a few different things together. The hand needs to have a circle complete a rotation around it when it hovers over an object. &lt;a href="http://betterthaneveryone.com"&gt;Clint Rutkas&lt;/a&gt; has already completed similar functionality in the &lt;a href="http://c4fkinect.codeplex.com/"&gt;Coding4Fun Kinect&lt;/a&gt; project with the addition of &lt;em&gt;Hover Buttons&lt;/em&gt; that have a relatively standard eventing model, although he doesn’t use a hand as his button, and instead uses simply circular buttons. &lt;a href="http://geekswithblogs.net/mbcrump/"&gt;Michael Crump&lt;/a&gt; has a done a nice tutorial on using them &lt;a href="http://geekswithblogs.net/mbcrump/archive/2011/07/04/kinecting-the-dots-adding-buttons-to-your-kinect-application.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want to use them slightly differently though. In both the original use in the Coding4Fun toolkit and Michael’s post they place the button’s &lt;em&gt;statically&lt;/em&gt; in the Window and have a cursor move over the top of them to &lt;em&gt;Click&lt;/em&gt; them. I am going to reverse this event flow and make the &lt;em&gt;Button itself&lt;/em&gt; the cursor and fire the &lt;em&gt;Hovering&lt;/em&gt; event inside the control whenever the button is sitting over the top of one of my buttons. &lt;/p&gt;

&lt;p&gt;To achieve this i am going to download the &lt;a href="http://c4fkinect.codeplex.com/"&gt;Coding4Fun Kinect Toolkit&lt;/a&gt;, add a reference to the library &lt;strong&gt;&lt;em&gt;Coding4Fun.Kinect.Wpf&lt;/em&gt;&lt;/strong&gt; and add a hover button to my &lt;em&gt;MainWindow.xaml&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;At the same time I’m going to setup my MainWindow.xaml with some new properties such as a background color, bigger screen size (1680x1045 – if your screen size is smaller you may have to change this to suit), and remove the navigation bars to make it run in full screen mode. &lt;/p&gt;

&lt;p&gt;My new MainWindow.xaml header looks like this (with the added reference to the Coding4Fun WPF and a :&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Window &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;KinectUserInterfaceDemo.MainWindow&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;WindowState&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Maximized&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;WindowStyle&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;SingleBorderWindow&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#1E1C37&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Controls&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;clr-namespace:Coding4Fun.Kinect.Wpf.Controls;assembly=Coding4Fun.Kinect.Wpf&amp;quot;
        &lt;/span&gt;&lt;span style="color: red"&gt;Title&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Kinect Demo&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1045&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1680&amp;quot;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now that we’ve added the right references, I’m going to add my &lt;em&gt;hand&lt;/em&gt; PNG to my project, and set it as a &lt;em&gt;Resource &lt;/em&gt;inside my project.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/37a00a01-bbc2-4db7-bd00-683e75ddc966_image_a45f4069-3bb4-42d4-b823-a24797e4c203.png" width="221" height="495" /&gt;&lt;/p&gt;

&lt;p&gt;With this done, i can add a &lt;em&gt;Hover Button&lt;/em&gt; to my xaml page and set its background as my hand PNG resource above;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;theGrid&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Canvas &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Transparent&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Controls&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;HoverButton &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Padding&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;kinectButton&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;ImageSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot;                                           
                                &lt;/span&gt;&lt;span style="color: red"&gt;ImageSource&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;/Resources/Hand_Basic.png&amp;quot;  
                                &lt;/span&gt;&lt;span style="color: red"&gt;ActiveImageSource&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;/Resources/Hand_Basic.png&amp;quot; 
                                &lt;/span&gt;&lt;span style="color: red"&gt;TimeInterval&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2000&amp;quot;  &lt;/span&gt;&lt;span style="color: red"&gt;Panel.ZIndex&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1000&amp;quot; /&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Canvas&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;I also want to create&amp;#160; a bunch of “&lt;em&gt;buttons&lt;/em&gt;” to press. So I’m going to go ahead and add the following;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;246&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;282&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#FFC800&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button1_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;670&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;282&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button2&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#FF5A0FC8&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button2_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 2&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1095&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;282&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#6BBD46&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button3&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button3_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 5&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;246&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;515&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#C80FA0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button4&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button4_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 4&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;670&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;515&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#26A0DA&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button5&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button5_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 5&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Left&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1095&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Canvas.Top&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;515&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#FF0000&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button6&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; 
        &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Click&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;button6_Click&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;FontSize&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;36&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;64&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Button 6&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;155&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Given that the Xbox Kinect user interface usually includes a window that shows the user, I’ll also add an Image control that I’ll fill later with a single video frame that the Kinect sends us through.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Image &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;videoImage&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;240&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;320&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bottom&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Image&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;These two additions should bring it all together for us to have a nice base use interface look that I’m going for;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/124d4177-51c7-4119-890c-87ff4312b38e_image_1dd0d69b-01c6-4b2c-a44d-a3750da26350.png" width="450" height="272" /&gt;&lt;/p&gt;

&lt;p&gt;Now for the fun stuff. Shift to the code behind for &lt;em&gt;MainWindow.xaml&lt;/em&gt; and follow the bouncing ball.&lt;/p&gt;

&lt;p&gt;Inside the constructor for my xaml page, I add a new click handler to my hover button, add a new class level &lt;em&gt;Runtime&lt;/em&gt; object and set up some handlers for it to tap into the window’s Loaded and Unloaded events.&lt;/p&gt;

&lt;pre class="code"&gt;Loaded += &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RoutedEventHandler&lt;/span&gt;(MainWindow_Loaded);
Unloaded += &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RoutedEventHandler&lt;/span&gt;(MainWindow_Unloaded);
kinectButton.Click += &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RoutedEventHandler&lt;/span&gt;(kinectButton_Clicked);
_runtime.VideoFrameReady += runtime_VideoFrameReady;
_runtime.SkeletonFrameReady += SkeletonFrameReady;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;As you can see from my code above, the Kinect SDK simply sets up a bunch of events that get fired for &lt;u&gt;&lt;em&gt;every&lt;/em&gt;&lt;/u&gt; Kinect frame that is received and processed. This means that we receive a call to my &lt;em&gt;SkeletonFrameReady&lt;/em&gt; and &lt;em&gt;runtime_VideoFrameReady&lt;/em&gt; methods around 20-30 times a second.&lt;/p&gt;

&lt;p&gt;Next add some logic for the &lt;em&gt;Loaded&lt;/em&gt; and &lt;em&gt;Unloaded&lt;/em&gt; events defined in our constructor above. This will setup our Kinect SDK Runtime object, configure &lt;em&gt;smoothing&lt;/em&gt; so that the joint movements we receive are slightly smoothed from the sensor (you don’t want our “hand” cursor jumping all around the screen when you wave you hand), and finally we need to setup a list of all our rectangular “buttons”;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;MainWindow_Loaded(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    InitializeButtons();
    &lt;span style="color: green"&gt;//Since only a color video stream is needed, RuntimeOptions.UseColor is used.
    &lt;/span&gt;_runtime.Initialize(&lt;span style="color: #2b91af"&gt;RuntimeOptions&lt;/span&gt;.UseDepthAndPlayerIndex | Microsoft.Research.Kinect.Nui.&lt;span style="color: #2b91af"&gt;RuntimeOptions&lt;/span&gt;.UseColor | &lt;span style="color: #2b91af"&gt;RuntimeOptions&lt;/span&gt;.UseSkeletalTracking);
    _runtime.SkeletonEngine.TransformSmooth = &lt;span style="color: blue"&gt;true&lt;/span&gt;;

    &lt;span style="color: green"&gt;//Use to transform and reduce jitter
    &lt;/span&gt;_runtime.SkeletonEngine.SmoothParameters = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;TransformSmoothParameters
    &lt;/span&gt;{
        Smoothing = 0.75f,
        Correction = 0.0f,
        Prediction = 0.0f,
        JitterRadius = 0.05f,
        MaxDeviationRadius = 0.04f
    };

    &lt;span style="color: green"&gt;//You can adjust the resolution here.
    &lt;/span&gt;_runtime.VideoStream.Open(&lt;span style="color: #2b91af"&gt;ImageStreamType&lt;/span&gt;.Video, 2, &lt;span style="color: #2b91af"&gt;ImageResolution&lt;/span&gt;.Resolution640x480, &lt;span style="color: #2b91af"&gt;ImageType&lt;/span&gt;.Color);
}
&lt;span style="color: blue"&gt;void &lt;/span&gt;MainWindow_Unloaded(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    _isClosing = &lt;span style="color: blue"&gt;true&lt;/span&gt;;
    _runtime.Uninitialize();
}
&lt;span style="color: blue"&gt;private void &lt;/span&gt;InitializeButtons()
{
    buttons = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Button&lt;/span&gt;&amp;gt;
                {
                    button1, 
                    button2, 
                    button3, 
                    button4, 
                    button5, 
                    button6
                };
}&lt;/pre&gt;

&lt;p&gt;Next, lets go ahead and add some logic into my &lt;em&gt;SkeletonFrameReady&lt;/em&gt; method so that i can hook up the &lt;em&gt;HoverButton&lt;/em&gt; I created above as a cursor. I’m going to be controlling its location on the screen relative to where a user’s hand is in the video frame. Then we’ll check if the hand is over any of my buttons, and if so begin the &lt;em&gt;Hovering &lt;/em&gt;event for the Kinect button that we’ve hijacked for our cursor.&lt;/p&gt;

&lt;p&gt;Below is the code I have for detecting my first person, finding out what &lt;a href="http://en.wikipedia.org/wiki/Laterality"&gt;laterality&lt;/a&gt; they are (right handed or left handed depending on which hand is higher),&amp;#160; and then allowing them to control the &lt;em&gt;HoverButton &lt;/em&gt;with that hand to “click” any buttons it is hovering over&lt;em&gt;;&lt;/em&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;SkeletonFrameReady(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;SkeletonFrameReadyEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(e.SkeletonFrame.Skeletons.Count() == 0) &lt;span style="color: blue"&gt;return&lt;/span&gt;;

    &lt;span style="color: #2b91af"&gt;SkeletonFrame &lt;/span&gt;skeletonSet = e.SkeletonFrame;

    &lt;span style="color: #2b91af"&gt;SkeletonData &lt;/span&gt;firstPerson = (&lt;span style="color: blue"&gt;from &lt;/span&gt;s &lt;span style="color: blue"&gt;in &lt;/span&gt;skeletonSet.Skeletons
                                &lt;span style="color: blue"&gt;where &lt;/span&gt;s.TrackingState == &lt;span style="color: #2b91af"&gt;SkeletonTrackingState&lt;/span&gt;.Tracked
                                &lt;span style="color: blue"&gt;orderby &lt;/span&gt;s.UserIndex &lt;span style="color: blue"&gt;descending
                                select &lt;/span&gt;s).FirstOrDefault();

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(firstPerson==&lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;

    &lt;span style="color: #2b91af"&gt;JointsCollection &lt;/span&gt;joints =  firstPerson.Joints;

    &lt;span style="color: #2b91af"&gt;Joint &lt;/span&gt;rightHand = joints[&lt;span style="color: #2b91af"&gt;JointID&lt;/span&gt;.HandRight];
    &lt;span style="color: #2b91af"&gt;Joint &lt;/span&gt;leftHand = joints[&lt;span style="color: #2b91af"&gt;JointID&lt;/span&gt;.HandLeft];

    &lt;span style="color: green"&gt;//find which hand is being used for cursor - is the user right handed or left handed?
    &lt;/span&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;joinCursorHand = (rightHand.Position.Y &amp;gt; leftHand.Position.Y)
                    ? rightHand
                    : leftHand;

    &lt;span style="color: blue"&gt;float &lt;/span&gt;posX = joinCursorHand.ScaleTo((&lt;span style="color: blue"&gt;int&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;SystemParameters&lt;/span&gt;.PrimaryScreenWidth, (&lt;span style="color: blue"&gt;int&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;SystemParameters&lt;/span&gt;.PrimaryScreenHeight).Position.X;
    &lt;span style="color: blue"&gt;float &lt;/span&gt;posY = joinCursorHand.ScaleTo((&lt;span style="color: blue"&gt;int&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;SystemParameters&lt;/span&gt;.PrimaryScreenWidth, (&lt;span style="color: blue"&gt;int&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;SystemParameters&lt;/span&gt;.PrimaryScreenHeight).Position.Y;

    &lt;span style="color: #2b91af"&gt;Joint &lt;/span&gt;scaledCursorJoint = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Joint
                            &lt;/span&gt;{
                                TrackingState = &lt;span style="color: #2b91af"&gt;JointTrackingState&lt;/span&gt;.Tracked,
                                Position = &lt;span style="color: blue"&gt;new &lt;/span&gt;Microsoft.Research.Kinect.Nui.&lt;span style="color: #2b91af"&gt;Vector
                                             &lt;/span&gt;{
                                                 X = posX,
                                                 Y = posY,
                                                 Z = joinCursorHand.Position.Z
                                             }
                            };
    OnButtonLocationChanged(kinectButton, buttons, (&lt;span style="color: blue"&gt;int&lt;/span&gt;)scaledCursorJoint.Position.X, (&lt;span style="color: blue"&gt;int&lt;/span&gt;)scaledCursorJoint.Position.Y);
}
&lt;span style="color: blue"&gt;private static void &lt;/span&gt;OnButtonLocationChanged(&lt;span style="color: #2b91af"&gt;HoverButton &lt;/span&gt;hand, &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Button&lt;/span&gt;&amp;gt; buttons, &lt;span style="color: blue"&gt;int &lt;/span&gt;X, &lt;span style="color: blue"&gt;int &lt;/span&gt;Y)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(IsButtonOverObject(hand, buttons)) hand.Hovering(); &lt;span style="color: blue"&gt;else &lt;/span&gt;hand.Release();

    &lt;span style="color: #2b91af"&gt;Canvas&lt;/span&gt;.SetLeft(hand, X - (hand.ActualWidth / 2));
    &lt;span style="color: #2b91af"&gt;Canvas&lt;/span&gt;.SetTop(hand, Y - (hand.ActualHeight / 2));
}
&lt;span style="color: blue"&gt;void &lt;/span&gt;kinectButton_Clicked(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: green"&gt;//call the click event of the selected button
    &lt;/span&gt;_selectedButton.RaiseEvent(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RoutedEventArgs&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ButtonBase&lt;/span&gt;.ClickEvent, _selectedButton));
}
&lt;span style="color: blue"&gt;public static bool &lt;/span&gt;IsButtonOverObject(&lt;span style="color: #2b91af"&gt;FrameworkElement &lt;/span&gt;hand, &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Button&lt;/span&gt;&amp;gt; buttons)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(_isClosing || !&lt;span style="color: #2b91af"&gt;Window&lt;/span&gt;.GetWindow(hand).IsActive) &lt;span style="color: blue"&gt;return false&lt;/span&gt;;

    &lt;span style="color: green"&gt;// get the location of the top left of the hand and then use it to find the middle of the hand
    &lt;/span&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;handTopLeft = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Point&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Canvas&lt;/span&gt;.GetTop(hand), &lt;span style="color: #2b91af"&gt;Canvas&lt;/span&gt;.GetLeft(hand));
    _handLeft = handTopLeft.X + (hand.ActualWidth / 2);
    _handTop = handTopLeft.Y + (hand.ActualHeight / 2);

    &lt;span style="color: blue"&gt;foreach &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Button &lt;/span&gt;target &lt;span style="color: blue"&gt;in &lt;/span&gt;buttons)
    {
        &lt;span style="color: #2b91af"&gt;Point &lt;/span&gt;targetTopLeft = target.PointToScreen(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Point&lt;/span&gt;());
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(_handTop &amp;gt; targetTopLeft.X
            &amp;amp;&amp;amp; _handTop &amp;lt; targetTopLeft.X + target.ActualWidth
            &amp;amp;&amp;amp; _handLeft &amp;gt; targetTopLeft.Y
            &amp;amp;&amp;amp; _handLeft &amp;lt; targetTopLeft.Y + target.ActualHeight)
        {
            _selectedButton = target;
            &lt;span style="color: blue"&gt;return true&lt;/span&gt;;
        }
    }
    &lt;span style="color: blue"&gt;return false&lt;/span&gt;;
}&lt;/pre&gt;

&lt;p&gt;And for good measure, I'll add my &lt;em&gt;runtime_VideoFrameReady&lt;/em&gt; method to fill our image with the current video frame;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;runtime_VideoFrameReady(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;ImageFrameReadyEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: green"&gt;//pull out the video frame from the eventargs and load it into our image object
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;PlanarImage &lt;/span&gt;image = e.ImageFrame.Image;
    &lt;span style="color: #2b91af"&gt;BitmapSource &lt;/span&gt;source = &lt;span style="color: #2b91af"&gt;BitmapSource&lt;/span&gt;.Create(image.Width, image.Height, 96, 96,
        &lt;span style="color: #2b91af"&gt;PixelFormats&lt;/span&gt;.Bgr32, &lt;span style="color: blue"&gt;null&lt;/span&gt;, image.Bits, image.Width * image.BytesPerPixel);
    videoImage.Source = source;
}&lt;/pre&gt;

&lt;p&gt;Last but not least, we’ll go ahead and add all the event handlers for our Buttons. My aim is just to notify you when they’ve been clicked – but you get the point so feel free to take it from here;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;button1_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 1 Clicked&amp;quot;&lt;/span&gt;);
}

&lt;span style="color: blue"&gt;private void &lt;/span&gt;button2_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 2 Clicked&amp;quot;&lt;/span&gt;);
}

&lt;span style="color: blue"&gt;private void &lt;/span&gt;button3_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 3 Clicked&amp;quot;&lt;/span&gt;);
}

&lt;span style="color: blue"&gt;private void &lt;/span&gt;button4_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 4 Clicked&amp;quot;&lt;/span&gt;);
}

&lt;span style="color: blue"&gt;private void &lt;/span&gt;button5_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 5 Clicked&amp;quot;&lt;/span&gt;);
}

&lt;span style="color: blue"&gt;private void &lt;/span&gt;button6_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;&amp;quot;Button 6 Clicked&amp;quot;&lt;/span&gt;);
}&lt;/pre&gt;

&lt;p&gt;You have to agree, that was simple huh? Amazingly simple.&lt;/p&gt;

&lt;p&gt;So there you have it – if you haven’t already, go out and have a play with the &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/"&gt;Kinect SDK&lt;/a&gt;. Your inner-youthful-programmer will thank you.&lt;/p&gt;

&lt;h3&gt;Here’s one I prepared earlier&lt;/h3&gt;

&lt;p&gt;I’ve taken the liberty of packaging up this project for your perusal. Feel free to download it and give it a bash!&lt;/p&gt;

&lt;p&gt;&lt;a href="/asset/examples/kinectbuttonpress1.zip"&gt;Example project download&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vyy_0cZBmL11BLIi-p0lsyBoviQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vyy_0cZBmL11BLIi-p0lsyBoviQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vyy_0cZBmL11BLIi-p0lsyBoviQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vyy_0cZBmL11BLIi-p0lsyBoviQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=IaQxgemAgd8:RY15ZjETi9E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=IaQxgemAgd8:RY15ZjETi9E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=IaQxgemAgd8:RY15ZjETi9E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=IaQxgemAgd8:RY15ZjETi9E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/EYOUTUqPn3o" height="1" width="1"/&gt;</description><pubDate>10/19/2011 3:00:54 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/10/19/remaking-the-xbox-kinect-hub--an-introduction-to-new-user-interfaces</feedburner:origLink></item><item><title>Your Call Is Not Important To Us</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/K-eYorqfjaY/your-call-is-not-important-to-us</link><description>&lt;p&gt;I have recently changed mobile service providers. The experiences I’ve had calling my old provider (Vodafone Australia) to cancel my plan and my new one (Telstra Australia) to buy their products have made it clear to me that companies that employ call centres for customer enquiries (mostly) have it completely wrong by modern customer service standards. Its seems really simple – so why does no one get it?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“…Your call is important to us, a customer care representative will be with you are soon as possible…”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 10px 0px 10px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/80fb0dae-b871-4868-bdc5-554b2fae7062_image_a320c5ca-df09-41b1-a039-170cb28b3c51.png" width="250" height="193" /&gt;So I've been on hold for 25 minutes to &lt;a href="https://twitter.com/#!/vodafone_au"&gt;Vodafone Australia&lt;/a&gt;. I think they may have sensed I was unhappy and calling to cancel my account – it just seems too coincidental that the longest time i have sat on hold in memory just happens to be when i call to close my account.&lt;/p&gt;  &lt;p&gt;So i continue to sit on hold, listening to an ever looping piano track.&lt;/p&gt;  &lt;p&gt;But this is not a new thing. We’ve all experienced it.&lt;/p&gt;  &lt;h3&gt;Customer service Is simple stupid&lt;/h3&gt;  &lt;p&gt;If you were going to setup a company/business tomorrow you’d operate under the assumption that the customer is king. This would extend to everything you would do – good customer service is the easiest way to lift your market share; make a customers experience so good, that they sell you to their friends. I’ve heard of a number of start ups recently that have doubled their market share by doing nothing but shifting their marketing budget to their support lines.&lt;/p&gt;  &lt;p&gt;You would take this single idea of serving the customer and spread it across all your marketing efforts and every transaction you do with them. We are in 2011 (almost 2012… wow time flies), so this would weight your decisions towards every business move you make in a big way. &lt;/p&gt;  &lt;p&gt;If you had a twitter feed you’d make sure to &lt;a href="http://nwbingham.com/2011/10/social-media-best-practices-acknowledge/"&gt;reply to a mention within a few hours max&lt;/a&gt; (if you break this golden rule, you are simply doing social media marketing &lt;em&gt;wrong&lt;/em&gt;). If you had an email you’d make an effort to reply to the sender within 24 hours (i believe in some instances an auto response is acceptable, but at the same time very similar to hearing on hold music – keep this in mind). If customers visited your website and needed support you’d setup a live chat. If customers called your place of business you’d pick up the phone… wait a second… what? that’s crazy.&lt;/p&gt;  &lt;h3&gt;If someone walked into your store…&lt;/h3&gt;  &lt;p&gt;This all brings me to my greatest single point of reference – human beings have been trading with each other for years, and i can bet you that when the romans were trading in their Forums they didn’t make people sit and wait for 20 minutes before talking to them. that's crazy talk; they’d lose business that way. if you have a shop front, and someone walks into your store, you engage them &lt;em&gt;instantly.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This very thought is huge right now in the Australian physical marketplace. A number of banks in Australia have taken this territory as real ground to compete on. Often they actually place a concierge at the front door to help direct you to the right service representative so that you don’t have to think about your reason for being there and increase their branch dwell time – It’s a proven technique. It works. Telstra does this in their stores a lot now too.&lt;/p&gt;  &lt;h3&gt;So when did it become acceptable to treat customers like shit?&lt;/h3&gt;  &lt;p&gt;Share holders like money, CEOs like to show short term gains to get their bonuses easily. Somewhere in the last 30 years the use of Interactive Voice Response (IVR) systems came along and the rise of VOIP lead to the rise of the Indian call centre – and CEOs lipped their lips with glee. &lt;/p&gt;  &lt;p&gt;All of a sudden the opportunity to lower costs must have seemed simply too good to miss. Couple this with a time before social media where you had to engage someone like &lt;a href="http://www.roymorgan.com/"&gt;Roy Morgan&lt;/a&gt; to actually call people in their homes and ask them questions to find out if they were unhappy and you have a perfect storm of customer dissatisfaction joined at the hip with a double whammy of actually having to spend more marketing budget to find out if people liked your changes or not. I don’t think many companies paid for enough market research (hell, they were trying to &lt;em&gt;cut costs&lt;/em&gt; right? spending extra budget on research defeats the point!). The status quo changed. All of a sudden it was OK to make people listen to Bach on repeat for 30 minutes before you served them. And that’s how it’s stayed for a long time now.&lt;/p&gt;  &lt;h3&gt;Times, they are a changing…&lt;/h3&gt;  &lt;p&gt;Some companies have woken up and smelt the coffee. A number of them come to mind straight away when thinking about good customer experiences – Aami Insurance uses this very situation as it’s key differentiator by saying “You’ll always speak to a real person” in all of its marketing material. Aami is my insurance company – something must have worked.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:f82ee9f5-ab33-474a-af97-ed1a3f94f75d" class="wlWriterSmartContent"&gt;   &lt;div&gt;&lt;embed height="252" type="application/x-shockwave-flash" width="448" src="http://www.youtube.com/v/A2byjWWfA_M?hl=en&amp;amp;hd=1" /&gt;&lt;/div&gt;    &lt;div style="width: 448px; clear: both; font-size: 0.8em"&gt;Aami Insurance “What about Me” Campaign&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;If i was working at a Telco present day, assessing the shift in all my power towards phone manufacturers such as Apple and this ever pressing migration to being simply “&lt;a href="http://www.dslreports.com/shownews/Apples-FaceTime-The-Beginning-Of-The-Dumb-Pipe-Revolution-109073"&gt;dumb pipes&lt;/a&gt;” I’d be taking stock of my customer engagement options in a very serious way. I’d be looking at ways to stand out from my competitors other than download limits. Changing my call centres to move to always speaking to a real person when you call seems like an easy win… no?&lt;/p&gt;  &lt;h3&gt;End Game&lt;/h3&gt;  &lt;p&gt;While I can whinge all i want about this, I feel I may be yelling into a vacuum. If i was a service provider like Vodafone or Telstra I’d be stupid not to see the opportunity – By making sure that you speak to a real person straight away you’d be a market leader in a market where the key differentiators are disappearing fast. People &lt;em&gt;do notice&lt;/em&gt; this kind of thing… Just sayin’.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CWOJJloYzMj-gDcWXfuQCBUa1lY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CWOJJloYzMj-gDcWXfuQCBUa1lY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CWOJJloYzMj-gDcWXfuQCBUa1lY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CWOJJloYzMj-gDcWXfuQCBUa1lY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=BMJya9kGf9I:iUY7Q0rbIMg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=BMJya9kGf9I:iUY7Q0rbIMg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=BMJya9kGf9I:iUY7Q0rbIMg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=BMJya9kGf9I:iUY7Q0rbIMg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/K-eYorqfjaY" height="1" width="1"/&gt;</description><pubDate>11/2/2011 6:34:14 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/11/02/your-call-is-not-important-to-us</feedburner:origLink></item><item><title>When you really need E-mail delivered – Signing your mail using Domain Keys/DKIM</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/Ks2Xo-3IGDM/when-you-really-need-your-email-delivered-ndash-signing-your-mail-using-domain-keysdkim</link><description>&lt;p&gt;So you’ve started sending email from your site/application, your application is doing well and you are now sending more e-mail daily. With this comes the fun of finding out that most of the email you now send ends up stuck in your customers spam filters – how did this happen? You aren’t a Nigerian scammer, and people opted-in to hear from you! At this point signing your mail may be the next step.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/47a8642f-1bfb-4894-9ded-b33f63eadf77_image_9cfa6bae-f070-4072-8fac-fead42a12623.png" width="300" height="135"&gt;I recently wrote a post on &lt;a href="/blog/2011/09/27/what-all-good-web-developers-should-know-about-sending-email"&gt;What good developers should know about sending mail&lt;/a&gt;, where i talked through the basics that all developers need to know about sending email before they simply start talking to &lt;a href="http://www.sendmail.com/sm/open_source/"&gt;SendMail&lt;/a&gt; or fire up an instance of &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx"&gt;SmtpClient&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;My post covered a few things you should make sure you do when sending email through code:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Send email from a real email address (hey it may sound crazy but people might want to reply…?)  &lt;li&gt;Never send mail from a domain you do not control (that’s what reply-to is there for…)  &lt;li&gt;Make sure your mail server’s forward and reverse DNS records are configured properly and match their HELO/EHLO greeting.  &lt;li&gt;Setup an SPF record/Sender ID DNS record for server authentication.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you are in the category of large sender, have stumbled onto the fact that a spammer used to use your IP address for nefarious means, or simply are having issues with the delivery rates of the mail you send out, one way you can add an extra &lt;em&gt;tick of approval&lt;/em&gt; to the mail that you send is to &lt;em&gt;sign your email&lt;/em&gt; using Domain Keys and DKIM.&lt;/p&gt; &lt;p&gt;Let’s take a look at how you would do this.&lt;/p&gt; &lt;h3&gt;Domain Keys and DKIM - A brief history&lt;/h3&gt; &lt;p&gt;The very problem you are currently facing – your recipients being unable to validate the email you send them are from &lt;em&gt;you&lt;/em&gt; is not a new one. Different fields on technology have faced this problem before the general development community mostly knew about it – in areas such as the Medical Industry, Defense and Engineering.&lt;/p&gt; &lt;p&gt;When faced with wanting a way to validate email without the hassle of using encryption and having to download the senders public PGP key, the people at Cisco developed a solution called &lt;em&gt;&lt;a href="http://identifiedmail.sourceforge.net/"&gt;Identified Internet Email&lt;/a&gt;&lt;/em&gt; that was aimed at allowing the sending party to verify the authenticity of a sender by investigating the senders DNS records (think encryption without the need for secrecy).&lt;/p&gt; &lt;p&gt;Yahoo, faced with the ever growing amount of spam on its Yahoo Mail platform loved this idea and wanted to take it a step further. This lead Yahoo Mail’s &lt;a href="http://en.wikipedia.org/wiki/Mark_Delany"&gt;Mark Delany&lt;/a&gt; to develop &lt;em&gt;DomainKeys&lt;/em&gt; to help verify the authenticity of a sender using a private key stored in the email and public key stored in a TXT record in sender’s DNS.&lt;/p&gt; &lt;p&gt;DomainKeys was then superseded by a combination of &lt;em&gt;Domain Keys &lt;/em&gt;and &lt;em&gt;Identified Internet Email&lt;/em&gt; called &lt;em&gt;DKIM&lt;/em&gt; (Domain Key Identified Mail). Domain Keys are thought of by the people of internet land (quite literally, the &lt;a href="http://en.wikipedia.org/wiki/IETF"&gt;&lt;em&gt;Internet Engineering Task Force&lt;/em&gt;&lt;/a&gt;) to be superseded but still supported for legacy sake. Luckily DKIM uses the same key storage, and just stores it’s email header differently.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Example Domain Key and DKIM Email Header&lt;/strong&gt;&lt;/p&gt;&lt;pre class="code"&gt;DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
 d=diaryofaninja.com; h=From:To:Subject;
 q=dns/txt; s=mailserver01; t=1321412507; bh=/53LpyJkzBXKAnLlbntG4C24JqY=;
 b=Im2WP82Ra+/rdZ6Rw1KtqbvnBMULshiwLI6mgDTkPekRFNBqhHZROFimt+XhhsUD/2S6RKvzkOfjS3e5+1WBXZOnf85NPA6gnPSZbutH2va+s9/XjPFx9fHDy8Kb0wpd
DomainKey-Signature: a=rsa-sha1; c=simple; d=diaryofaninja.com;
 h=From:To:Subject; q=dns; s=mailserver01;
 b=dqE0DZWbSEUZ7ZrfRe5M5cJJlzMPgKEJdb3VTPIoHxtCrmWESR+XeFGQl5YRStfXqcc8oGE/ZbdaIsK3Ov9pBdMbVlxYvIHNXK7G4iIHE8mfms/OA/QkWwpwi9/HV/ep;&lt;/pre&gt;
&lt;h3&gt;Getting it up and running on your servers&lt;/h3&gt;
&lt;p&gt;So you’ve decided to take the plunge and setup signed mail for your application.&lt;/p&gt;
&lt;p&gt;Before you proceed you need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Access to the DNS configuration for your domain name (we’ll be adding some new TXT records) 
&lt;li&gt;Either access to your mail server or the ability to change your site’s code. &lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Generating signing keys&lt;/h3&gt;
&lt;p&gt;The first thing you’ll need to do is generate a set of private and public encryption keys that will be used to sign your email. I am a Microsoft developer by trade so i am running on Windows – to generate DKIM keys I use &lt;a href="http://www.slproweb.com/products/Win32OpenSSL.html"&gt;Open SSL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.slproweb.com/products/Win32OpenSSL.html"&gt;Download Open SSL&lt;/a&gt; (if you don’t already have it you’ll also need the Visual C++ 2011 Redistributable installed from &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=29"&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Open a command prompt window and run the following commands (with the domain name you are generating keys for filling in the blanks)&lt;/p&gt;
&lt;p&gt;openssl genrsa -out rsa.private.{your domain name goes here} 768&lt;/p&gt;
&lt;p&gt;openssl rsa -in rsa.private.{your domain name goes here} -out rsa.public.{your domain name goes here} -pubout -outform PEM&lt;/p&gt;
&lt;p&gt;I have taken the liberty of writing a little batch file that takes your domain name as a parameter and runs these for you (an easy to use idiot proof solution).&lt;/p&gt;&lt;pre class="code"&gt;@ECHO off
IF EXIST rsa.private.%1 GOTO keys_already_exist
 
REM Execute OpenSSL and request that it generates a 768 long private key 
openssl genrsa -out rsa.private.%1 768

REM Now Execute OpenSSL and generate a public key from the private one created above
openssl rsa -in rsa.private.%1 -out rsa.public.%1 -pubout -outform PEM
ECHO.
echo Files created for %1
ECHO.

GOTO finished_key_gen

:keys_already_exist

ECHO.
ECHO Keys for the domain name %1 have not been created because the files already exist.
ECHO Please delete your keys before trying again.
ECHO.

:finished_key_gen&lt;/pre&gt;
&lt;p&gt;Save this to a file name &lt;strong&gt;generate-dkim.bat&lt;/strong&gt; and then run it by simply typing:&lt;/p&gt;&lt;pre class="code"&gt;generate-dkim my-domain-name.com&lt;/pre&gt;
&lt;p&gt;Once you’ve run Open SSL you should have two files, a private key and a public key. The public key will go in your DNS as a TXT record and you will use the private key to sign outgoing mail using DKIM.&lt;/p&gt;
&lt;h3&gt;Adding the keys to your DNS&lt;/h3&gt;
&lt;p&gt;Both Domain Keys and DKIM use the same procedure for storing your public signing keys:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A base DNS record that lets people know whether you sign all your email or just some of it, along with a contact address for bad mail. 
&lt;li&gt;Any number of “selectors” or different keys. This allows you to have different keys for different mail servers, rotate keys year-to-year or any other requirement you could think of that would require more than one public key to exist at a time.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The public key you have created in Open SSL will look similar to:&lt;/p&gt;&lt;pre class="code"&gt;-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhANWCczM6lXpTDUpoAbKPOuUN7fI9b0Lk
H9BZv/ikUrEqm6FWuBKZk2AHDH7nAVvh8pqICfVpKNSFNiZIarbDOZFL3HyDyFE1
LSDTpiWQAli1+aTH7pJnvH1NR6wTaFYCfQIDAQAB
-----END PUBLIC KEY-----&lt;/pre&gt;
&lt;p&gt;Before you put this in your DNS you will need to remove the header and footer from the file (i.e. “-----BEGIN PUBLIC KEY-----“), and remove any line breaks from the string.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A Modified public key:&lt;/em&gt;&lt;pre class="code"&gt;MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhANWCczM6lXpTDUpoAbKPOuUN7fI9b0LkH9BZv/ikUrEqm6FWuBKZk2AHDH7nAVvh8pqICfVpKNSFNiZIarbDOZFL3HyDyFE1LSDTpiWQAli1+aTH7pJnvH1NR6wTaFYCfQIDAQAB&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;Then use this to create your DNS TXT records. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example Domain Keys or DKIM DNS records&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Base record – tells people whether all your mail is signed or not and who to send bad mail too:&lt;/p&gt;&lt;pre class="code"&gt;_domainkey.mycompany.com IN TXT "o=~\; r=helpdesk@mycompany.com"&lt;/pre&gt;
&lt;p&gt;A “Selector” record - a domain can have multiple public keys at a time, and they are separated by different sub-domains or “selectors” – the example shows how you can split this by giving each mail server its own key: &lt;pre class="code"&gt;mailserver01._domainkey.mycompany.com IN TXT "k=rsa\; p={DomainKey/DKIM public key goes here}" &lt;/pre&gt;
&lt;h3&gt;Sending DomainKey/DKIM Email (through code)&lt;/h3&gt;
&lt;p&gt;Once you have setup your DNS you’ll want to send signed email – one way to do this is using code during the send process of your application (remember when you abstracted all your email functionality into a helper class? this is the time is all pays of…)&lt;/p&gt;
&lt;p&gt;As i am a .Net developer i look for .Net solutions – there are many, many DKIM implementations in other languages if you are not a .Net kind of guy/gal, Google is your friend here.&lt;/p&gt;
&lt;p&gt;My favourite implementation is a project called &lt;a href="https://github.com/dmcgiv/DKIM.Net"&gt;DKIM.Net on GitHub&lt;/a&gt; as its free, supports both DomainKeys and DKIM, and will get you up and running with minimal fuss or code-smell.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;privateKey = &lt;span style="color: #2b91af"&gt;PrivateKeySigner&lt;/span&gt;.LoadFromFile(Server.MapPath(&lt;span style="color: #a31515"&gt;"~/rsa.private.mydomain.com"&lt;/span&gt;));
&lt;span style="color: blue"&gt;var &lt;/span&gt;DnsSelector = &lt;span style="color: #a31515"&gt;"mailserver01"&lt;/span&gt;;
&lt;span style="color: blue"&gt;var &lt;/span&gt;dkimSigner = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DkimSigner&lt;/span&gt;(privateKey, &lt;span style="color: #a31515"&gt;"mywebsite.com"&lt;/span&gt;, DnsSelector, &lt;span style="color: blue"&gt;new string&lt;/span&gt;[] { &lt;span style="color: #a31515"&gt;"From"&lt;/span&gt;, &lt;span style="color: #a31515"&gt;"To"&lt;/span&gt;, &lt;span style="color: #a31515"&gt;"Subject" &lt;/span&gt;});
&lt;span style="color: blue"&gt;var &lt;/span&gt;domainkey = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DomainKeySigner&lt;/span&gt;(privateKey, &lt;span style="color: #a31515"&gt;"mywebsite.com"&lt;/span&gt;, DnsSelector, &lt;span style="color: blue"&gt;new string&lt;/span&gt;[] { &lt;span style="color: #a31515"&gt;"From"&lt;/span&gt;, &lt;span style="color: #a31515"&gt;"To"&lt;/span&gt;, &lt;span style="color: #a31515"&gt;"Subject" &lt;/span&gt;});
        
&lt;span style="color: #2b91af"&gt;MailMessage &lt;/span&gt;msg = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MailMessage&lt;/span&gt;();
msg.To.Add(&lt;span style="color: #a31515"&gt;"me@mycompany.com"&lt;/span&gt;);
msg.Subject = &lt;span style="color: #a31515"&gt;"DKIM test message"&lt;/span&gt;;
msg.Body = &lt;span style="color: #a31515"&gt;"Hello world"&lt;/span&gt;;
msg.From = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MailAddress&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"my-signed@email-address.com"&lt;/span&gt;);
        
msg.DomainKeySign(domainkey);
msg.DkimSign(dkimSigner);

&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SmtpClient&lt;/span&gt;().Send(msg);
&lt;/pre&gt;
&lt;p&gt;If using an Open Source free library puts the fear of {INSERT NAME OF DEITY} in you, there are a number of commercial .Net products that are just as nice to use (but cost money, obviously):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.afterlogic.com/mailbee-net/email-components"&gt;Mailbee.net from AfterLogic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lesnikowski.com/mail/"&gt;Mail.dll from Lesnikowski&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CAVEAT:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are planning on using &lt;em&gt;Simple&lt;/em&gt; rather than &lt;em&gt;Relaxed&lt;/em&gt; DKIM signing, conducting your email signing through code can often make your signing fail as your mail server may add a new/different &lt;em&gt;Date&lt;/em&gt; header after you send your email to it that may cause the signature of your e-mail to become invalidated (because it was signed using a different header – one with a different/earlier date).&lt;/p&gt;
&lt;h3&gt;Sending DomainKey/DKIM Email (using your mail server)&lt;/h3&gt;
&lt;p&gt;The other way you can implement the signing of outgoing mail is to employ the Domain Key/DKIM signature as the mail goes out the door – using your SMTP/mail server to do the signing.&lt;/p&gt;
&lt;p&gt;Sadly if you are using the IIS SMTP server or Exchange to send your mail there is no out of the box support for DKIM or Domain Keys, so because of this my preferred approach is to install and configure a separate locked down (not accessible outside of the local box etc.) version of &lt;a href="http://www.hmailserver.com/"&gt;hMailserver&lt;/a&gt; (free) on a non-standard port. hMailServer is light weight and allows you to easily setup DKIM signing for outgoing mail with zero changes to your applications code.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/86902610-4921-468c-956a-5fe1153cbd1c_image_3.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/f84df39a-fe1e-427b-b75b-6ec34d47d858_image_thumb.png" width="450" height="338"&gt;&lt;/a&gt;&lt;br&gt;&lt;em&gt;A screenshot of hMailServer’s Administration console.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are also a number of commercial software packages that allow you to use DKIM on Windows Server:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.emailarchitect.net/domainkeys/"&gt;EA DomainKeys/DKIM for IIS SMTP Server and Exchange Server from AdminSystem&lt;/a&gt;&amp;nbsp;&lt;br&gt;(a IIS SMTP/Exchange Plugin)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.smartertools.com/smartermail/mail-server-software.aspx"&gt;Smarter Mail&amp;nbsp; by SmartTools&lt;/a&gt;&lt;br&gt;(a fully functional enterprise mail server replacement – they additionally offer a free version of their product)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.port25.com/products/prod_features_basic.html" target="_blank"&gt;PowerMTA from Port 25&lt;/a&gt;&lt;br&gt;(a fully featured mail server/email delivery platform)&lt;/p&gt;
&lt;h3&gt;Almost there - Testing your DomainKey/DKIM signed email&lt;/h3&gt;
&lt;p&gt;Once you have configured all of the above and want to actually test that everything is working as it should, you’ll want to know of some easy ways to test the whole thing is working:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gmail&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gmail is by far the easiest option to testing the DKIM and Domain Key signing of your emails as they add the validation results for incoming email to the header of every email they receive. To access this simply send an email to your Gmail account, open the email and select “Show original” from the options list.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example of the header GMAIL puts on your email&lt;/em&gt;:&lt;/p&gt;&lt;pre class="code"&gt;Authentication-Results: 
spf=neutral (google.com: 10.10.10.10 is neither permitted nor denied by best guess record for domain of my-website-domain.com) 
dkim=pass header.i=@my-website-domain.com
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed;
 d=my-website-domain.com; h=From:To:Subject;
 q=dns/txt; s=mailserver01; t=1321412507; bh=/53LpyJkzBXKAnLlbntG4C24JqY=;
 b=Im2WP82Ra+/rdZ6Rw1KtqbvnBMULshiwLI6mgDTkPekRFNBqhHZROFimt+XhhsUD/2S6RKvzkOfjS3e5+1WBXZOnf85NPA6gnPSZbutH2va+s9/XjPFx9fHDy8Kb0wpd
DomainKey-Signature: a=rsa-sha1; c=simple; d=my-website-domain.com;
 h=From:To:Subject; q=dns; s=mailserver01;
 b=dqE0DZWbSEUZ7ZrfRe5M5cJJlzMPgKEJdb3VTPIoHxtCrmWESR+XeFGQl5YRStfXqcc8oGE/ZbdaIsK3Ov9pBdMbVlxYvIHNXK7G4iIHE8mfms/OA/QkWwpwi9/HV/ep;
&lt;/pre&gt;
&lt;h3&gt;Port 25&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.port25.com" target="_blank"&gt;Port25&lt;/a&gt; offers a really cool service in the form of its email report service.&lt;/p&gt;
&lt;p&gt;If you send an email to &lt;a href="mailto:check-auth@verifier.port25.com"&gt;check-auth@verifier.port25.com&lt;/a&gt; they will reply with a report on the email you’ve sent them.&lt;/p&gt;
&lt;p&gt;They take this one step further by allowing you to specify the reply email &lt;a href="mailto:check-auth-jsmith=yourdomain.com@verifier.port25.com"&gt;check-auth-jsmith=yourdomain.com@verifier.port25.com&lt;/a&gt; (example shows &lt;a href="mailto:jsmith@yourdomain.com"&gt;jsmith@yourdomain.com&lt;/a&gt; getting the report)&lt;/p&gt;
&lt;h3&gt;Alternative to all this additional work&lt;/h3&gt;
&lt;p&gt;If you have read this far you may be feeling that you’ve got a considerable amount of work ahead of you/behind you just to get this additional functionality out the door. You aren’t far from the truth, but if you’re even reading this post you are probably at the point where the additional work is &lt;strong&gt;well worth it or just plain-old “has to be done” &lt;/strong&gt;in order to get your mail delivered to peoples inboxes. &lt;/p&gt;
&lt;p&gt;Alternatively, If you want to have all this additional functionality without the leg work and don’t mind paying for it there is always the option of outsourcing the job of sending your application’s email to a third-party. &lt;/p&gt;
&lt;p&gt;A number of relatively cost-effective start-ups have sprung up to serve this very need;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sendgrid.com/" target="_blank"&gt;SendGrid&lt;/a&gt; (options starting at FREE for 200 emails a month) &amp;lt;- have used this service and they are awesome&lt;/p&gt;
&lt;p&gt;&lt;a href="http://postageapp.com/" target="_blank"&gt;PostageApp&lt;/a&gt; (options starting at $9/month for 9,000 emails)&lt;/p&gt;
&lt;p&gt;Pros/Cons to outsourcing your email sending:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sleep easy knowing that your email delivery problems are keeping someone else up and night. 
&lt;li&gt;Usually setting it up and trailing their services simply require you changing your outgoing SMTP server address (setup with no fuss).&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;These services often delivery email using a generic domain name (&lt;a href="mailto:{random-Guid}@sendgrid.me"&gt;{random-Guid}@sendgrid.me&lt;/a&gt;) not your website’s domain name (however they usually offer upgrades to make this happen for an additional charge) 
&lt;li&gt;You still have to setup your DNS for their services to be “recognised” as being able to send from your domain. 
&lt;li&gt;Additional cost that can be FREE if you simply put in some effort.
&lt;li&gt;You don’t have full control of the send end-to-end (this might make you/your sysadmin boss unhappy).&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Signing your outgoing email with DKIM and Domain Keys will not save the manatees, tie your shoe laces, or make you “lose 10 pounds in just 24 hours” but it will make your email recipients (and their mail servers on their behalf) trust your email’s authenticity a lot more, and inturn help you stay out of peoples e-mail Junk/Spam folder. You may think it’s simply easier to outsource your mail sending to someone like SendGrid – either way, if you are having delivery issues and &lt;strong&gt;need to have your email delivered&lt;/strong&gt;, signing your email is definitely a step in the right direction.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/t6TPtgNyiE-cDMwqlal-xDxSZAE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t6TPtgNyiE-cDMwqlal-xDxSZAE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/t6TPtgNyiE-cDMwqlal-xDxSZAE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t6TPtgNyiE-cDMwqlal-xDxSZAE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0qN7Aqppxt0:sFxAhwqW5dc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0qN7Aqppxt0:sFxAhwqW5dc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0qN7Aqppxt0:sFxAhwqW5dc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=0qN7Aqppxt0:sFxAhwqW5dc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/Ks2Xo-3IGDM" height="1" width="1"/&gt;</description><pubDate>11/16/2011 1:04:17 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/11/16/when-you-really-need-your-email-delivered-ndash-signing-your-mail-using-domain-keysdkim</feedburner:origLink></item><item><title>Scheduling TeamCity backups in Windows</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/wUo8c_usXFQ/scheduling-teamcity-backups-in-windows</link><description>&lt;p&gt;Jetbrains’ build server software &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; is an awesome product to get up and running with continuous integration and deployment, however with its ease of operation it leaves a few nice to have business features aside. One of these is Scheduled backup – and if there is anything that your career has probably taught you to date, it’s that when things break, having a backup is priceless.&lt;/p&gt;  &lt;p&gt;The default database storage that comes with an installation of TeamCity is HSQL and while I currently have a single build server instance presiding over more than 100 build configurations flawlessly while running HSQL for data storage there is always the fear that when something goes wrong, it'll really go wrong.&lt;/p&gt;  &lt;p&gt;To allay this fear there are a few things that you should do:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Use a storage device other than the pre-packaged HSQL such as SQL Express (i will cover this in a later post). &lt;/li&gt;    &lt;li&gt;Run a scheduled backup of your build server configuration regularly so that in the case of failure you can come back where you left off. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first task ill cover in a later blog post, but the second one we’ll go through today.&lt;/p&gt;  &lt;p&gt;TeamCity comes packaged with a number of command line tools for running maintenance tasks against your build server. The main one we’ll look at in this post is called &amp;quot;&lt;em&gt;maintainDB&lt;/em&gt;&amp;quot; – &lt;a href="http://confluence.jetbrains.net/display/TCD6/Creating+Backup+via+maintainDB+command-line+tool"&gt;Documented here&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="code"&gt;maintainDB backup -C -D -L -P&lt;/pre&gt;

&lt;p&gt;The above makes it really easy flexible for use in a batch file and Windows Scheduled Task scenario – what this post will cover.&lt;/p&gt;

&lt;h3&gt;Getting stuck in&lt;/h3&gt;

&lt;p&gt;The first this we need to do is add a few environment variable paths to your Windows TeamCity server so that the TeamCity maintenance tool can find everything:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;TEAMCITY_APP_DIR &lt;/li&gt;

  &lt;li&gt;TEAMCITY_DATA_PATH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do this, login to your TeamCity Server and click on &lt;em&gt;Start.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Right click on &lt;em&gt;My Computer&lt;/em&gt; and select &lt;em&gt;Properties.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click the link on the left marked &lt;em&gt;Advanced System Settings&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a5dd4ce3-3503-4877-9ffc-9435ff63e223_image_4736502e-8143-4aed-a838-3c802ac89f4c.png" width="450" height="411" /&gt;&lt;/p&gt;

&lt;p&gt;Now click on &lt;em&gt;Environmental Variables&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/21e5cc02-6830-47af-a5b5-d0bc8dd9b8c5_image_bc847643-7d74-4e81-ae8a-fad86ead8913.png" width="400" height="450" /&gt;&lt;/p&gt;

&lt;p&gt;Now click on &lt;em&gt;New&lt;/em&gt; and enter the following paths (your configuration may be different, so please investigate these locations):&lt;/p&gt;

&lt;p&gt;“TEAMCITY_APP_DIR” – the location of your TeamCity web application directory (on my server this is set to the default of &lt;em&gt;C:\TeamCity\webapps\ROOT)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;“TEAMCITY_DATA_PATH” – the location of your TeamCity data directory. This is inside the windows user profile of the user who installed it. You find this out by access the &lt;em&gt;Server Configuration&lt;/em&gt; page in the TeamCity site/admin console (on my server this is &lt;em&gt;C:\Users\dougr\.BuildServer).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/b202c33d-a8ff-490b-8ad6-77727d7553ee_image_60538f8f-12fe-4b37-bf46-647eeacbb387.png" width="399" height="474" /&gt;&lt;/p&gt;

&lt;p&gt;Now that we’ve set the environment variables needed to make this all work, open notepad and copy the following script into a new file. You will need to change the fifth line to the reflect your TeamCity backup path. &lt;/p&gt;

&lt;p&gt;This is a folder inside the Windows User Profile of the user who installed the server – again for me this is &lt;em&gt;C:\Users\dougr\.BuildServer\backup.&lt;/em&gt;&lt;/p&gt;

&lt;pre class="code"&gt;@ECHO off
::
:: REPLACE THE FOLLOWING PATH WITH YOUR TEAMCITY BACKUP DIRECTORY
::
SET TeamcityDataFolder=C:\Users\dougr\.BuildServer\backup

IF &amp;quot;%1&amp;quot;==&amp;quot;&amp;quot; GOTO NoParams

SET CopyToPath=%1
ECHO.
ECHO Currently path: %~dp0
ECHO TeamCity Data Folder: %TeamcityDataFolder%

net stop &amp;quot;TeamCity Web Server&amp;quot;

CD C:\TeamCity\bin
CALL maintainDB backup -C -D -L -P -F backup-temp

net start &amp;quot;TeamCity Web Server&amp;quot;

:: GET THE LOCAL DATE IN ANY REGION
:: Taken from http://stackoverflow.com/a/3202796/115749

SETLOCAL ENABLEEXTENSIONS
if &amp;quot;%date%A&amp;quot; LSS &amp;quot;A&amp;quot; (set toks=1-3) else (set toks=2-4)
for /f &amp;quot;tokens=2-4 delims=(-)&amp;quot; %%a in ('echo:^|date') do (
for /f &amp;quot;tokens=%toks% delims=.-/ &amp;quot; %%i in ('date/t') do (
set '%%a'=%%i
set '%%b'=%%j
set '%%c'=%%k))
if %'yy'% LSS 100 set 'yy'=20%'yy'%
set Today=%'yy'%-%'mm'%-%'dd'% 
ENDLOCAL &amp;amp; SET v_year=%'yy'%&amp;amp; SET v_month=%'mm'%&amp;amp; SET v_day=%'dd'%


SET BackupFileName=TeamCityBackup-%V_Year%-%V_Month%-%V_Day%.zip

SET CopyToPath=%CopyToPath%\%BackupFileName%
ECHO Copying Backup to: %CopyToPath%
move %TeamcityDataFolder%\backup-temp.zip %CopyToPath%

GOTO Finished

:NoParams

ECHO.
ECHO ERROR:
ECHO You haven't defined an output path for your backup. call this script again 
ECHO followed by the Path you'd like to save your backup to. 
ECHO.
ECHO i.e. backup-teamcity.bat C:\mybackupfolder
GOTO:EOF

:Finished
cd %~dp0
ECHO Backup finished&lt;/pre&gt;

&lt;p&gt;Save this file somewhere you put the rest of your server maintenance scripts if you have any – I saved mine as &lt;em&gt;C:\MaintenanceScripts\backup-teamcity.bat&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can run this script by entering the batch file name into an elevated command prompt window and adding a parameter to indicate where you want your backup saved.&lt;/p&gt;

&lt;pre class="code"&gt;C:\MaintenanceScripts\backup-teamcity.bat C:\SaveMyBackupsInThisFolder&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; 

    &lt;br /&gt;The above batch file has been tested successfully on a few of my TeamCity installations successfully. You shouldn’t have anything to fear, however if you don’t fully understand the above batch script buyer beware – do you research before using it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;What is this going to do to my server?&lt;/h3&gt;

&lt;p&gt;The batch file i have written above does the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Takes an incoming parameter as the destination to copy the backup to. &lt;/li&gt;

  &lt;li&gt;Stops the TeamCity Web Server service. &lt;/li&gt;

  &lt;li&gt;Runs the TeamCity maintenance tool to create a backup. &lt;/li&gt;

  &lt;li&gt;Saves the backup as &lt;em&gt;TeamCityBackup-yyyy-mm-dd.zip&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;Copies the backup to your folder of choice. &lt;/li&gt;

  &lt;li&gt;Starts the TeamCity Web Server service. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Schedule that bad buoy…&lt;/h3&gt;

&lt;p&gt;Now we have everything in place we need to create a scheduled task to run our backup.&lt;/p&gt;

&lt;p&gt;Open Task Scheduler and click on &lt;em&gt;Create Basic Task&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/0e6643c7-29da-4d82-837f-7a22af238e5c_image_1a40da07-47f9-4cd7-a3a4-cb14ba07df17.png" width="450" height="321" /&gt;&lt;/p&gt;

&lt;p&gt;In the next Window give your task a name and click &lt;em&gt;Next &lt;/em&gt;– I’ve named mine “Daily TeamCity Backup”&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/27aab4f4-86ce-4095-ba61-b0bc119dcabd_image_88422e97-5fa3-453c-aec1-ff37680e0d54.png" width="450" height="309" /&gt;&lt;/p&gt;

&lt;p&gt;Now select how often you want your backup to run and click &lt;em&gt;Next&lt;/em&gt; – I’ve set &lt;em&gt;Daily&lt;/em&gt; as I want a regular backup.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/94a1da8f-749b-480c-bcab-e95c10edb7e2_image_bc6c37fe-2eda-4dbf-9aa1-6a645dca72f0.png" width="450" height="309" /&gt;&lt;/p&gt;

&lt;p&gt;Now set the time you want your backup to run and click &lt;em&gt;Next&lt;/em&gt; – I’ve set mine to 12:00am so that i runs when nothing else is happening on the build server.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/df6493ff-6af2-49bb-8cf4-828f8a5a1dc6_image_1fb6c67a-0a49-48a9-9b55-efe229cd5b5d.png" width="450" height="309" /&gt;&lt;/p&gt;

&lt;p&gt;Now select that you want your task to &lt;em&gt;Start a program&lt;/em&gt; and click &lt;em&gt;Next&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/25a602b6-c918-430c-84c0-6a1c68335c0c_image_a627b50f-b558-4698-b95e-e574832632de.png" width="450" height="309" /&gt;&lt;/p&gt;

&lt;p&gt;Enter the path to the batch file you saved above and enter the path you want the backup to be copied to as the only argument.&lt;/p&gt;

&lt;p&gt;Click &lt;em&gt;Next.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/6ad0671f-655d-4f77-88dd-f350d92b5a4c_image_edbe0188-3099-4fbd-9493-1728d0b04001.png" width="450" height="309" /&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Tick the box marked&lt;em&gt; “Open the Properties dialog for this task when I click Finish”&lt;/em&gt; and click &lt;em&gt;Finish.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/c1874703-16f8-4ee4-93d5-72b7145045bc_image_a5c5d00c-a959-4f8a-aa21-1cae2c2c5f12.png" width="450" height="309" /&gt;&lt;/p&gt;

&lt;p&gt;Select the radio button marked “&lt;em&gt;Run whether user is logged on or not”&lt;/em&gt; and then click the button marked “&lt;em&gt;Change User of Group” – &lt;/em&gt;This allows us to set what user the task runs as. As we are doing a number of things in our batch file that require Windows to be running as an elevated user we want ours to run as &lt;em&gt;SYSTEM.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a60740cb-a0bc-4ac0-b8ec-44c84767428a_image_780e46a4-44e7-4018-b508-9a0d1447f091.png" width="450" height="335" /&gt;&lt;/p&gt;

&lt;p&gt;Enter the user &lt;em&gt;SYSTEM&lt;/em&gt; and click ok and then OK again.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/b6bb76b3-88e7-4d61-9bad-c75be5930df1_image_3d610f1a-fafc-4de6-8a78-63085a568358.png" width="450" height="239" /&gt;&lt;/p&gt;

&lt;p&gt;You’re done!&lt;/p&gt;

&lt;p&gt;It’s worth testing the task once to make sure everything happens as it should by running it manually in the task scheduler settings page.&lt;/p&gt;

&lt;p&gt;One more thing to note is that this will fill your server’s hard drive with backups every night. If you only want to keep a certain number you can use the this post in conjunction with the scripts in my post &lt;a href="/blog/2011/02/22/set-up-scheduled-log-file-cleaning-for-windows-servers-running-iis"&gt;Set up scheduled log file cleaning for Windows Servers running IIS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vCxL1dxgDyrHIjWm22SonpCfVFE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vCxL1dxgDyrHIjWm22SonpCfVFE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vCxL1dxgDyrHIjWm22SonpCfVFE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vCxL1dxgDyrHIjWm22SonpCfVFE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=oDVXf722c14:D2ZsBYeC5CE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=oDVXf722c14:D2ZsBYeC5CE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=oDVXf722c14:D2ZsBYeC5CE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=oDVXf722c14:D2ZsBYeC5CE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/wUo8c_usXFQ" height="1" width="1"/&gt;</description><pubDate>12/13/2011 8:49:08 PM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/12/13/scheduling-teamcity-backups-in-windows</feedburner:origLink></item><item><title>Kung-fu showdown – One design to rule them all</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/7mLLKp5EvXM/kungfu-showdown-ndash-one-design-to-rule-them-all</link><description>&lt;p&gt;My old design lasted a long time. In fact it was the design that I launched this blog with in 2009. I loved it when I launched the site as although it wasn’t the easiest design on your reading eyes it had a certain shock/wow factor. Times change though, so i wanted a fresh look – and i wanted to claim some of that wow factor back – So if you’ve been reading for a while you’ll notice that the change has been quite dramatic. As always though, the Ninjas had to stay.&lt;/p&gt; &lt;h3&gt;Circa 2009-2011&lt;/h3&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/7248851a-d926-4de7-99ac-a260c2f3f8ae_image_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/e7f72ffd-7758-44af-9f54-c5e33fe8026c_image_thumb.png" width="454" height="325"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I realised more and more that while i liked writing content for the site i was sometimes unable to fully read an article because of a lack of readability/contrast. Part of this was my dated TFT Lenovo x61 screen (Lenovo loves to release dimly lit screens).&lt;/p&gt; &lt;h3&gt;New look &amp;amp; feel&lt;/h3&gt; &lt;p&gt;If you take a look around at the 2011 blogosphere everyone has made been making a big deal out of readability. &lt;a href="http://www.hanselman.com/blog/HireAndPayADesignerAndBeHappy.aspx"&gt;Hanselman&lt;/a&gt; has made the change, Jeff Atwood of Coding Horror has &lt;a href="http://www.codinghorror.com/blog/"&gt;always been all about it&lt;/a&gt;, and you only have to take a look at the new Microsoft/Windows Phone Branding to get a feel of where things are heading. Content is King and making it as consumable as possible is the key.&lt;/p&gt; &lt;p&gt;With this in mind, I pulled open Photoshop and went to work creating something new.&lt;/p&gt; &lt;p&gt;My thoughts included:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The Windows Phone Metro design guides.  &lt;li&gt;Jeff Atwood’s love of white and space.  &lt;li&gt;A love of more minimal designs  &lt;li&gt;Making it all above the copy&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/66171bb6-f74e-451d-bc00-7f8469f7fcc2_image_6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/de6b0146-f086-4f4b-a28c-c8c491129233_image_thumb_2.png" width="454" height="321"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Speaking of Ninjas, over the years many people have asked me how I drew or where i got my Ninjas from. You have probably seen similar ones around the interwebs a few times. Stackoverflow even has a banner that has similar Ninjas for all the world to see.&lt;/p&gt; &lt;p&gt;The story behind them is simple. I drew them in Adobe Photoshop using a tutorial for Adobe Illustrator from &lt;a href="http://blog.spoongraphics.co.uk/tutorials/illustrator-tutorial-create-a-gang-of-vector-ninjas" target="_blank"&gt;Chris Spooner over at Spoon Graphics&lt;/a&gt;. I must thank Chris for this great tutorial – even though it actually taught me more about Photoshop than it did Illustrator as i had to do it the hard way and create vectors and smart objects in Photoshop.&lt;/p&gt; &lt;h3&gt;HTMLification&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://www.imdb.com/title/tt0388139/quotes?qt=qt0186983" target="_blank"&gt;Everyone needs at least one Dutch mate…&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I am very lucky to be surrounded by oober cool/intelligent developers at my day job, so was very excited to have our resident Dutch HTML/Client-side Guru &lt;a href="http://www.afterlight.com.au" target="_blank"&gt;John Van Der Loo&lt;/a&gt; around to help me with making the new design awesomely HTMLified. Like most developers I cut my teeth on HTML years ago, and like most developers who don’t specialise in front end development you’ll know that it can sometimes be a bit of a pain in the ass when it comes to niggling little cross browser issues. That’s why i brought in my resident expert.&lt;/p&gt; &lt;p&gt;I wanted it not only to be beautiful, readable and easy on the eyes, but i also wanted maximum cross browser friendliness with any bells and whistles that come with it along the way. &lt;a href="http://www.twitter.com/geekyjohn" target="_blank"&gt;John&lt;/a&gt; is one of &lt;em&gt;those&lt;/em&gt; guys when it comes to perfection, so there was no one better to have around when putting it together.&lt;/p&gt; &lt;h3&gt;One size does not fit all&lt;/h3&gt; &lt;p&gt;One of the great things about using new technologies such as HTML 5 and CSS 3 is that you get &lt;a href="http://www.w3.org/TR/css3-mediaqueries/"&gt;media-query&lt;/a&gt; support that allows you to build pages for multiple screen sizes. No longer was the site going to be limited to 1024x768 viewers (or me on my Lenovo x61). Everyone could be happy. Even those of you tuning in on your mobile devices on the train to work (well at least if noone else is, i am…) get get involved. If you have a large screen you can see it all happen before your eyes magically just by resizing the very window you are reading this post in.&lt;/p&gt; &lt;p&gt;&lt;em&gt;Mobile&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/4a770dab-a3eb-485a-b912-4841fa69e235_image_8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/60f0c7fa-11ee-4f6a-b285-246dd89f2518_image_thumb_3.png" width="204" height="414"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Mobile landscape&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/5a6a2fdf-447c-4b5e-8e51-92cccfaf0525_image_10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/7a31af2c-c9cc-4015-b38e-a06963e6d0e1_image_thumb_4.png" width="204" height="277"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;800x600&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/c8a549e3-8042-407c-a1e7-2c0c6bb0d888_image_12.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/18aefd5f-e24a-4bcb-af0d-e55253bc9125_image_thumb_5.png" width="244" height="219"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;1024x768&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/4b108952-eb86-45e1-9836-d9c749a342a4_image_14.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/60b363b4-eaac-47ee-81c2-f50840ca2902_image_thumb_6.png" width="244" height="173"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;1440x900 and higher&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/379250d3-f5e1-4ebd-b809-26d6ab318eda_image_16.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/203e670e-0cb4-45b0-aff0-a2b81fa26773_image_thumb_7.png" width="244" height="163"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;HTML 5/CSS3 Love&lt;/h3&gt; &lt;p&gt;Another really cool feature of CSS 3 is transforms. If you hover over the Ninja’s in a browser that supports transforms you will see an Easter egg hidden on the site – the Shuriken’s spin on the second Ninja. &lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;@-webkit-keyframes &lt;/span&gt;rotate {
    &lt;span style="color: red"&gt;from &lt;/span&gt;&lt;span style="color: blue"&gt;{     -webkit-transform:rotate(0)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-webkit-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(360deg)&lt;/span&gt;; }
}

&lt;span style="color: blue"&gt;@-moz-keyframes &lt;/span&gt;rotate {
    &lt;span style="color: red"&gt;from &lt;/span&gt;&lt;span style="color: blue"&gt;{     -moz-transform:rotate(0)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-moz-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(360deg)&lt;/span&gt;; }
}

&lt;span style="color: blue"&gt;@-webkit-keyframes &lt;/span&gt;rotate2 {
    &lt;span style="color: red"&gt;from &lt;/span&gt;&lt;span style="color: blue"&gt;{    -webkit-transform:rotate(720deg)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-webkit-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(-720deg)&lt;/span&gt;; }
}

&lt;span style="color: blue"&gt;@-moz-keyframes &lt;/span&gt;rotate2 {
    &lt;span style="color: red"&gt;from &lt;/span&gt;&lt;span style="color: blue"&gt;{    -moz-transform:rotate(720deg)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-moz-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(-720deg)&lt;/span&gt;; }
}

&lt;span style="color: blue"&gt;@-webkit-keyframes &lt;/span&gt;rotate3 {
    &lt;span style="color: red"&gt;from &lt;/span&gt;&lt;span style="color: blue"&gt;{    -webkit-transform:rotate(-1080deg)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-webkit-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(1080deg)&lt;/span&gt;; }
}

&lt;span style="color: blue"&gt;@-moz-keyframes &lt;/span&gt;rotate3 {
    &lt;span style="color: red"&gt;from&lt;/span&gt;&lt;span style="color: blue"&gt;{    -moz-transform:rotate(-1080deg)&lt;/span&gt;; }
    &lt;span style="color: maroon"&gt;to &lt;/span&gt;{    &lt;span style="color: red"&gt;-moz-transform&lt;/span&gt;:&lt;span style="color: blue"&gt;rotate(1080deg)&lt;/span&gt;; }
}

&lt;/pre&gt;
&lt;p&gt;John has also used all the new HTML 5 semantic tags such as &lt;a href="http://www.w3.org/TR/html5/sections.html#the-article-element" target="_blank"&gt;article&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/html5/sections.html#the-nav-element" target="_blank"&gt;nav&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/html5/sections.html#the-header-element" target="_blank"&gt;header&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/html5/sections.html#the-footer-element" target="_blank"&gt;footer&lt;/a&gt; and &lt;a href="http://www.w3.org/TR/html5/sections.html#the-section-element" target="_blank"&gt;section&lt;/a&gt; (along with using &lt;a href="http://www.modernizr.com/" target="_blank"&gt;Modernizer&lt;/a&gt; to allow all those IE 6/7 users to still see everything). Awesome!&lt;/p&gt;
&lt;p&gt;All up I really like the new look and I hope you do too.&lt;/p&gt;
&lt;p&gt;Let me know what you think.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/avBepq8S99fLCwbcJ9-SpvWbh_0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/avBepq8S99fLCwbcJ9-SpvWbh_0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/avBepq8S99fLCwbcJ9-SpvWbh_0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/avBepq8S99fLCwbcJ9-SpvWbh_0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=38_8FGdxTcc:uOrMinPN4Xw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=38_8FGdxTcc:uOrMinPN4Xw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=38_8FGdxTcc:uOrMinPN4Xw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=38_8FGdxTcc:uOrMinPN4Xw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/7mLLKp5EvXM" height="1" width="1"/&gt;</description><pubDate>12/14/2011 6:25:34 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2011/12/14/kungfu-showdown-ndash-one-design-to-rule-them-all</feedburner:origLink></item><item><title>MCTS 70-515 Web Applications Development with .NET 4 - In Review</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/pseNwLI-Twg/mcts-70515-web-applications-development-with-net-4--in-review</link><description>&lt;p&gt;Recently I studied and sat a Microsoft Certification for ASP.Net 4.0 and MVC. As much as some people on the web cause grief to anyone who’s interested in certifications I must state that I actually did learn a lot about other parts of the framework that day-to-day I never touch. The great thing about this experience was that while yes I did learnt about some parts of the ASP.Net framework that I’ll never touch because in the real world you wouldn’t use them, I also found I learnt about a number of other parts of the framework that I didn’t know were there and these new bits of knowledge will help me daily.&lt;/p&gt; &lt;h3&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/7f5a2aca-a810-4052-bf8c-c7dc91ff3f96_image_6.png" width="196" height="244"&gt;Web Applications Development with Microsoft .NET Framework 4&lt;/h3&gt; &lt;p&gt;A year and a half ago I started studying for the &lt;a href="http://www.microsoft.com/learning/en/us/exam.aspx?id=70-562" target="_blank"&gt;certification 70-562&lt;/a&gt; because my old employer needed a few more developers to get certified to maintain their Microsoft Partnership level (as some members of staff that &lt;em&gt;&lt;a href="http://brucefwebster.com/2008/04/11/the-wetware-crisis-the-dead-sea-effect/" target="_blank"&gt;were certified had left&lt;/a&gt;&lt;/em&gt;). The 70-562 exam covers ASP.Net 3.5 from a more classic approach, learning about how to use&lt;em&gt; lots of web controls&lt;/em&gt; to do everything, and at the time it felt a little dated as nearly everyone i knew working with ASP.Net was from a “I can code HTML blindfold and prefer having control over things” background and therefore wrote their own HTML without the need to use controls to create &lt;em&gt;mangled HTML or use tables for things on their behalf &lt;/em&gt;(I kid… I kid…).&lt;/p&gt; &lt;p&gt;The 70-515 exam feels a lot more grounded in the real world that we all live and work in though, as it covers all the ASP.Net 3.5 controls etc. with a little less importance placed on them and also includes ASP.Net MVC 3 as well – which seeing my work mostly consists of only ASP.Net MVC&amp;nbsp; this addition made me feel like&amp;nbsp; I could really get value from the training and study that comes with doing this certification.&lt;/p&gt; &lt;p&gt;Microsoft recommends that developers wanting to sit this exam have the following experience:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Candidates for this exam are professional Web developers who use Microsoft Visual Studio. Candidates should have a minimum of two to three years of experience developing Web-based applications by using Visual Studio and Microsoft ASP.NET. Candidates should be experienced users of Visual Studio 2008 and later releases and should have a fundamental knowledge of the .NET Framework 4 programming languages (C# or Microsoft Visual Basic). In addition, candidates should understand how to use the new features of Visual Studio 2010 and the .NET Framework 4. &lt;p&gt;Candidates should also have a minimum of one year of experience with the following: &lt;ul&gt; &lt;li&gt;Accessing data by using Microsoft ADO.NET and LINQ  &lt;li&gt;Creating and consuming Web and Windows Communication Foundation (WCF) services  &lt;li&gt;State management  &lt;li&gt;ASP.NET configuration  &lt;li&gt;Debugging and deployment  &lt;li&gt;Application and page life-cycle management  &lt;li&gt;Security aspects such as authentication and authorization  &lt;li&gt;Client-side scripting languages  &lt;li&gt;Internet Information Server (IIS)  &lt;li&gt;ASP.NET MVC&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;Areas covered&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Configuring and Deploying Web Applications (10 %)&lt;/li&gt; &lt;li&gt;Consuming and Creating Server Controls (20 %)&lt;/li&gt; &lt;li&gt;Working with Data and Services (17 %)&lt;/li&gt; &lt;li&gt;Troubleshooting and Debugging Web Applications (16 %)&lt;/li&gt; &lt;li&gt;Working with ASP.NET AJAX and Client-Side Scripting (15 %)&lt;/li&gt; &lt;li&gt;Targeting Mobile Devices (5 %)&lt;/li&gt; &lt;li&gt;Programming Web Applications (17 %)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;From the above topics about the only thing I think I have no use for and will probably die without ever putting the skills I've learnt into practice are the sections on &lt;em&gt;SharePoint Web Controls.&lt;/em&gt; I won’t go into why I feel this is the case as there are enough people on the interwebs bitching about Sharepoint without me adding my 2c.&lt;/p&gt; &lt;h3&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/bb1c48e5-ecd3-4d3c-8c4e-5275172ea5ac_image_5.png" width="201" height="244"&gt;Study Material&lt;/h3&gt; &lt;p&gt;I spent about 3.5 months studying for the exam and based my study around the following routine:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Studied and took notes from one chapter of the &lt;a href="http://www.amazon.com/MCTS-Self-Paced-Training-Exam-70-515/dp/0735627401" target="_blank"&gt;70-515 Microsoft Training book&lt;/a&gt; a week including doing all the example tutorials and quick-quizzes.&lt;/li&gt; &lt;li&gt;Used study-mode on the Microsoft training book software (useless and full of wrong answers).&lt;/li&gt; &lt;li&gt;Used study-mode and certification mode on the &lt;a href="http://www.measureup.com/70-515-CS-TS-Web-Applications-Development-with-Microsoft-NET-Framework-4-C-Final-P1729.aspx" target="_blank"&gt;MeasureUp training software&lt;/a&gt; for 70-515.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I must share my opinion on a few things;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The testing software that came with the training book had around 30% wrong answers for the questions on it&lt;/strong&gt;. That’s right &lt;strong&gt;30%!&lt;/strong&gt; It also only has a total of 55 questions on the CD – to put this in perspective my actual exam was 76 questions long, so I didn’t feel the software could possible cover enough areas to gain much value from them. I almost recommend that anyone purchasing the training book literally throw the testing software CD in the bin. It’s that bad.&lt;strong&gt; The software is also quite buggy as it crashed on me a few times&lt;/strong&gt;.&lt;/p&gt; &lt;h3&gt;Why care about Testing Software?&lt;/h3&gt; &lt;p&gt;A lot of people recommend against doing any training example questions as part of your study and prefer that you just “know the material like the back of your hand”. I disagree with this, as I think it is quite important to be familiar with the format that you sit the exam under as it simplifies the process of you sitting it by bringing it down to just having to know the correct answers instead of having to take in the exam process on the day as well. I also think that if you’ve never sat a Microsoft or Cisco etc exam before that it is important to familiarise yourself with the &lt;em&gt;style of questions&lt;/em&gt; as they nearly all are asked in a sneaky way to usually test you on more than just common knowledge (i.e. showing you 3 &lt;em&gt;correct&lt;/em&gt; answers but only one &lt;em&gt;truly correct &lt;/em&gt;one based on the context of the question).&lt;/p&gt; &lt;p&gt;When I started to use the trial exam software included in the Microsoft training book I instantly felt I was wasting my time. A large number of the questions on the CD either had small mistakes in their code samples that would mean that in the real world they wouldn’t compile, or had blatantly incorrect answers. &lt;/p&gt; &lt;p&gt;This made me want to find a more reliable source for training questions. &lt;/p&gt; &lt;p&gt;The options I looked at where:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.measureup.com/70-515-CS-TS-Web-Applications-Development-with-Microsoft-NET-Framework-4-C-Final-P1729.aspx" target="_blank"&gt;Measure Up 70-515&lt;/a&gt; – 150 Questions – $109.00&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.transcender.com/practice-exam/microsoft/70-515.kap" target="_blank"&gt;Transcender 70-515&lt;/a&gt; – 114 Questions – $139.00&lt;/p&gt; &lt;p&gt;They both have trial software that allows you to get a feel for their products. The &lt;a href="http://www.transcender.com/" target="_blank"&gt;Transcender&lt;/a&gt; software definitely feels more thorough as a software product (the &lt;a href="http://www.measureup.com/" target="_blank"&gt;MeasureUp&lt;/a&gt; software feels like it was written before the end of the cold war – maybe an over exaggeration but it definitely feels dated) however for the price versus number of questions I took the MeasureUp software as i felt it would probably give me a greater variety of questions and therefore I’d get more value out of it.&lt;/p&gt; &lt;p&gt;In the end there were actually around 5 questions in the MeasureUp software that had similar issues to the Microsoft training software in that there were small errors or code that wouldn’t compile. Other than this though I did feel that the MeasureUp software did help me greatly in refining my speed in being able to deduce what was &lt;em&gt;really being asked&lt;/em&gt; in the questions, because as previously mentioned, the Microsoft style of asking questions is often quite deceiving – &lt;a href="http://www.measureup.com/" target="_blank"&gt;MeasureUp’s&lt;/a&gt; software replicated this quite well.&lt;/p&gt; &lt;p&gt;I must also add that on emailing MeasureUp informing them of the questions that had issues, they refunded my entire purchase price and released a new version of the question pack (the software checks for updates every time you load it) within a short time frame – this is quite commendable as it shows that they both care about the quality of the questions and also care about their customers.&lt;/p&gt; &lt;h3&gt;How I found the certification test.&lt;/h3&gt; &lt;p&gt;The test that i sat on the day was 76 questions over 3 hours. There were a number of disclaimers I agreed to before sitting the test and one of these was that some of the questions where un marked to test upcoming questions for future exam participants and because of this I am unsure how many where actually scored. All the trial exam software I sat always talked about the test being 54 questions, so the answer to how many questions were actually tested lies probably somewhere in the middle.&lt;/p&gt; &lt;p&gt;Overall I found the exam quite balanced to the split that I showed it to be testing above in this post, however I found it interesting that a number of the MeasureUp trial exam software questions where actually in the real test which added a little relief. Apparently the exam questions are randomly pulled from a large question pool for each participant, which makes me think that if this is the case that i must have had a lot of luck getting questions i had already studied.&lt;/p&gt; &lt;p&gt;I did find the test to definitely not be a walk in the park. I consider my knowledge of the ASP.net framework to be quite high and I was definitely slowed in my answering of a number of the questions. Because of this I recommend studying the material very thoroughly if you have not being doing ASP.net for as long as they recommend.&lt;/p&gt; &lt;h3&gt;My moment of anxiety&lt;/h3&gt; &lt;p&gt;On the day of my exam I sat my test at a &lt;a href="http://www.prometric.com/Microsoft/default.htm" target="_blank"&gt;Prometric&lt;/a&gt; testing centre on Market street in Sydney. Upon completing the test it congratulated me on passing and then asked me to wait while my score was submitted. Halfway through this wait, the testing software crashed and a Modal window told me to speak to a Prometric customer support member. &lt;strong&gt;This completely freaked me out&lt;/strong&gt; as I instantly worried that my score wouldn’t be recorded and I would have to sit the test again. I was told all was fine however they were unable to give me a score print out and that Microsoft would contact me once the test result had been processed which could take up to a week. When my colleague who’d sat the test on the same day received not only his print out on the day but also was contacted by Microsoft the next day I definitely had a day or two of rising fear of being “lost in the system” – happily I have since received my notification from Microsoft, but the wait definitely didn’t make my day :-)&lt;/p&gt; &lt;h3&gt;Conclusion&lt;/h3&gt; &lt;p&gt;Overall I found the certification a good test of broad skill and knowledge in the ASP.Net framework and would recommend it to other developers who want to not only add another piece of paper to their resume but also because i feel I learnt a number of things i wouldn’t have learnt through my day-to-day job that i can both put to use and also add to my confidence in knowledge of ASP.Net.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fe7dRQiLf2IV4Mt_DgCt3K7f-rM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fe7dRQiLf2IV4Mt_DgCt3K7f-rM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fe7dRQiLf2IV4Mt_DgCt3K7f-rM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fe7dRQiLf2IV4Mt_DgCt3K7f-rM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=HcolNBLaLo0:rvHERYbB0o8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=HcolNBLaLo0:rvHERYbB0o8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=HcolNBLaLo0:rvHERYbB0o8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=HcolNBLaLo0:rvHERYbB0o8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/pseNwLI-Twg" height="1" width="1"/&gt;</description><pubDate>1/1/2012 2:12:01 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/01/01/mcts-70515-web-applications-development-with-net-4--in-review</feedburner:origLink></item><item><title>Corporate accounts payable Nina Speaking. Just a Moment… Let’s talk about Workplace noise</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/voVqXrgmPDU/corporate-accounts-nina-speaking-just-a-momenthellip</link><description>&lt;p&gt;Whether you’re working on a website for your local corner store, or writing software on the next super-jumbo jet’s &lt;a href="http://www.seas.gwu.edu/~mfeldman/ada-project-summary.html#Air_Traffic_Management_Systems_"&gt;critical systems&lt;/a&gt;, distractions can contribute to a pretty unhappy working life as a developer or technical writer. Our very trade requires making calculations, creating complex logical paths and holding large amounts of information in your mind all at the same time. Please give us some peace and quiet while we do this… Please!&lt;/p&gt;  &lt;p&gt;In the Mike Judge movie &lt;a href="http://www.imdb.com/title/tt0151804/"&gt;&lt;em&gt;Office Space&lt;/em&gt;&lt;/a&gt;&lt;em&gt; &lt;/em&gt;they show a scene where the main character Peter Gibbons (Ron Livingston) arrives to work and slowly over the course of a morning experiences the living hell that can be a programming job in a loud cube farm; including being seated next to a department secretary who repeats her greeting ad nauseam (this very scene is where I got the title for this post).&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/9f93c2eb-7cc7-4736-bb27-73840945a3df_image_a4a61d3a-8318-4c6c-807b-503e7de220f5.png" width="221" height="184" /&gt;Developers want quiet workplaces because there are less distractions. Less distractions means more efficiently written, elegant code (yes this is an assumption without stats to back it up, but I can tell you from my own personal experience that the best code I write is either at night after everyone at work has left, in the morning before everyone has arrived or quietly in my home office after a long day, as all these places offer less distractions).&lt;/p&gt;  &lt;p&gt;Studies have &lt;a href="http://www.mendeley.com/research/influence-of-noise-characteristics-on-behavioral-aftereffects/"&gt;repeatedly&lt;/a&gt;&amp;#160;&lt;a href="http://www.mendeley.com/research/individual-differences-susceptibility-irrelevant-speech-effect/"&gt;shown&lt;/a&gt; that distractions reduce performance in the workplace. And yet these studies aren’t actually specifically looking at developers at all! Most of the studies I've read simply look at cognitive performance and recall – no wonder as developers we’re all a grumpy non-communicative bunch with our headphones in.&lt;/p&gt;  &lt;p&gt;And yet at nearly every place I’ve worked that isn’t a tech start-up, management has implemented or tried to implement open plan workspaces “for easy interaction”. They then usually add workplace music or play the music channel from cable TV under the guise that it will make the workplace &lt;strong&gt;“more fun”&lt;/strong&gt; and “&lt;strong&gt;more productive”&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;Are they all crazy?&lt;/p&gt;  &lt;h3&gt;He’s plugged in!&lt;/h3&gt;  &lt;p&gt;In the movie &lt;em&gt;&lt;a href="http://www.imdb.com/title/tt1285016/" target="_blank"&gt;The Social Network&lt;/a&gt;&lt;/em&gt;, whenever someone tries to talk to a developer working with headphones on, Sean Parker (played by Justin Timberlake) discourages disturbing the them by yelling “He’s plugged in!”. I have had some non-developer co-workers mention this in the past&amp;#160; as a reason for ignoring the problem of a noisy workplace, but this is tantamount to an Ostrich placing its head in the sand. “But he can just listen to music on his/her headphones to help him/her concentrate if he/she has to”. Some workplaces actually have the complete opposite and &lt;strong&gt;ban&lt;/strong&gt; headphones as they may be considered &lt;strong&gt;anti-social&lt;/strong&gt;…!!&lt;/p&gt;  &lt;p&gt;Just to show you how much of a large increase in productivity that workers can gain from not having intermittent distractive noises in the workplace, Herman Miller did a study of devices that &lt;em&gt;mask&lt;/em&gt; the sound of other things in the workplace by creating &lt;em&gt;white noise&lt;/em&gt; to drown out everyone around you. The results of this study are astounding to say the least:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Studies of sound masking systems have reported &lt;a href="http://www.hermanmiller.com/MarketFacingTech/hmc/solution_essays/assets/se_Sound_Masking_in_the_Office.pdf" target="_blank"&gt;productivity gains of 8 to 38%, stress reduction of up to 27%, and job satisfaction increases of 125 to 174%.&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Stepping back from these results would lead you to believe that placing these devices in every workplace would be the thing to do right away – hell, think of the ROI within 2 years of installing them!&lt;/p&gt;  &lt;p&gt;Anyone who works in sound or music production will tell you though that this is a fallacy, and that if you have one loud channel in your mix it’s always better to turn the loud channel down than the soft channels louder. Add to this that I can only assume that after sitting inside a workplace that sounded like a datacentre server room all day (to drown out all the noise) I may have been more productive but i almost certainly won’t have the greatest hearing after a few years.&lt;/p&gt;  &lt;h3&gt;We are legion hear us…&lt;/h3&gt;  &lt;p&gt;While some of my non-developer readers may think that all of this may sound a bit excessive and immature (“we can’t all have what we want, people making noise are just doing their job”), I must remind most of you that if you are in an industry that relies on software products or services workplace satisfaction is really what most employee longevity boils down to. Good developers know this and will simply move on if you don’t create the right environment for them to go about their business – again this may sound immature or unrealistic but you only have to conduct your business badly for a period of a few months to a year before you’ll start to experience what we in &lt;em&gt;the biz&lt;/em&gt; call the &lt;em&gt;&lt;a href="http://brucefwebster.com/2008/04/11/the-wetware-crisis-the-dead-sea-effect/" target="_blank"&gt;Dead Sea Effect&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Basically, this boils down to a simple truth: If you make your employee’s working days filled with multiple, never read again &lt;a href="http://www.urbandictionary.com/define.php?term=tps%20report" target="_blank"&gt;TPS reports&lt;/a&gt; and constant aural distractions, your good developers will leave and you’ll be left with only the average ones who are too scared of losing their jobs to make a peep. This is not the best outcome for any business that relies on software production – usually losing even a bad developer costs you dearly as you train a new one up on your businesses processes.&lt;/p&gt;  &lt;p&gt;When it comes to loud noise in the workplace I am not the first person to bring a mention of this over time – pretty much anyone worth their salt in the programming game has talked about it at some time.&lt;/p&gt;  &lt;p&gt;As usual Jeff Atwood eloquently and humorously makes his point very well in his post in 2004 &lt;em&gt;&lt;a href="http://www.codinghorror.com/blog/2004/12/this-is-your-anti-productivity-pod.html" target="_blank"&gt;This is your Anti-Productivity Pod&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Joel Spolsky does an equally good job when talking about &lt;a href="http://www.joelonsoftware.com/articles/fog0000000043.html" target="_blank"&gt;&lt;em&gt;The Joel Test for Software Development Companies&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, &lt;/em&gt;by placing quiet on a list of must haves for anyone writing software as part of their job.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.joelonsoftware.com/articles/fog0000000043.html" target="_blank"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/bb2e6f1b-1c29-47be-9e78-f88895fc381a_image_46e681cc-c086-42f5-b5bc-bcc0c005873d.png" width="244" height="227" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;So what do we do about it&lt;/h3&gt;  &lt;p&gt;None of the answers below may be rocket science, as nearly all workers enjoy a bit of peace of quiet even if they aren’t in the role of software production, but some of the things required to make it happen can sometimes appear to be simply too hard for some management teams to even begin to think about.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Create a workplace that is quiet.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This has got to be first and foremost. If you have a loud office environment maybe move your developers to a separate part of the building or floor, you may think we’ll feel like we are missing out by not hearing about how many times Barry from finance barfed at the last work party – but I can almost assure you we won’t; we’re developers after all, so a lot of the time hearing about how many times the guy next to you totally p0wned on Battlefield 3 last night or how sweet the surf was before work today is scales of economy more exciting or fulfilling to us.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Create a culture of respecting each other’s aural and brain space.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;As with most things that add to &lt;em&gt;the vibe&lt;/em&gt; of an office culture, culture in general is something that is built, it doesn’t happen instantly or magically; &lt;em&gt;so start small today&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;While you will never hear me mention &lt;em&gt;The Social Network&lt;/em&gt; and “there is some good insight there” in the same sentence ever again, if you take the movie at face value I think they’re onto a good thing here – if Sean Parker really did yell at people for disturbing programmers he has moved up a notch from the &lt;em&gt;douche of the universe&lt;/em&gt; that the mass-media has painted him as over the last decade.&lt;/p&gt;  &lt;p&gt;If you see that someone is busy in thought smashing away on a keyboard, maybe walking up to their desk to ask them for the 10th time today whether they are any closer to fixing “that bug” will be counterproductive – maybe send them an email instead. If you use internal chat or messaging and someone is marked as “away” or “busy” maybe they actually are – again maybe shoot them an email or wait for their status to change.&lt;/p&gt;  &lt;p&gt;If you see someone else doing something similar to another colleague maybe stop them and have a word – when you are next busy and someone does the same thing you’ll thank yourself. Together it’s never too late to implement change.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conduct meetings in meeting rooms or separate workspaces away from other workers.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Last but not least, if you think that general banter and office music are a bad distraction, placing 10 people in an open plan meeting room in the middle of an office is taking things to another level. Organise meetings away from workspaces and people’s desks. If you have segregated areas that are away from the main office floor such as meeting rooms or glassed-in sections of the office floor, &lt;em&gt;use them.&lt;/em&gt; Your developers and co-workers will thank you.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;We can all create a little more Zen in the our workplace, but recognizing that it’s actually a problem is definitely the first step.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:4a3b2008-7e3c-41a5-8f41-5f95555f8a33" class="wlWriterSmartContent"&gt;   &lt;div&gt;&lt;embed height="252" type="application/x-shockwave-flash" width="448" src="http://www.youtube.com/v/0N05WL2NlLo?hl=en&amp;amp;hd=1" /&gt;&lt;/div&gt; &lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CdvCaSLXjiBHoly38Fed2msJyos/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CdvCaSLXjiBHoly38Fed2msJyos/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CdvCaSLXjiBHoly38Fed2msJyos/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CdvCaSLXjiBHoly38Fed2msJyos/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=PUB-fudoQGE:IpUCgdisycw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=PUB-fudoQGE:IpUCgdisycw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=PUB-fudoQGE:IpUCgdisycw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=PUB-fudoQGE:IpUCgdisycw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/voVqXrgmPDU" height="1" width="1"/&gt;</description><pubDate>1/10/2012 6:16:07 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/01/10/corporate-accounts-nina-speaking-just-a-momenthellip</feedburner:origLink></item><item><title>Arachnophobia – Spider, Spider go away, come again another day</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/yjfSdWLQHTI/arachnophobia--spider-spider-go-away-come-again-another-day</link><description>&lt;p&gt;While working on soon-to-be-released projects there has often been a need to make a staging/testing website publicly accessible for client testing. This is a slippery slope if search engine spiders get in and index your site before the rest of the world is meant to see it (it happens more than you’d like to think) – If it happens to be a website you are building for something that the rest of the world shouldn’t see yet such as a product/service launch, having it leak too early can often make or break you. They have a word that describes this very fear of spiders&amp;#160; – it’s called Arachnophobia.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.flickr.com/photos/e_monk/3569222884/"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 10px 0px 10px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/4279aa8a-6395-490a-867a-7163da928999_image_03a28c8d-8241-4eb8-87c8-4a7490437b6f.png" width="250" height="166" /&gt;&lt;/a&gt;Arachnophobia is a library designed to address this very concern. It contains a .Net &lt;a href="http://msdn.microsoft.com/en-us/library/zec9k340(v=vs.71).aspx"&gt;HttpModule&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/5c67a8bd(v=vs.71).aspx"&gt;HttpHandler&lt;/a&gt; that tells visiting search engine spiders that you don’t want your site indexed.&lt;/p&gt;  &lt;h3&gt;But I didn’t link to my site anywhere?&lt;/h3&gt;  &lt;p&gt;When you really need search engines to index you they’re nowhere to be found – other times they poke their nose in when you really wish they wouldn’t.&lt;/p&gt;  &lt;p&gt;One of the sometimes strange problems that developers come unstuck with when it comes to being indexed too early is that they assume that because they haven’t linked to their site anywhere that search engines won’t index your site. &lt;/p&gt;  &lt;p&gt;The main reason they face this issue is that sites that list &lt;a href="http://www.webmasterworld.com/forum3/25278.htm"&gt;registration&lt;/a&gt; and &lt;a href="http://www.domainsnext.com/deleteddomainslists.htm"&gt;de-registration&lt;/a&gt; of domain names often &lt;strong&gt;link to new or changed domains&lt;/strong&gt;. This means that if Google comes along to one of these sites and finds a link to your new domain name &lt;strong&gt;www.super-cool-unicorns.com&lt;/strong&gt; it will come for a visit without a second thought.&lt;/p&gt;  &lt;h3&gt;What is Arachnophobia?&lt;/h3&gt;  &lt;p&gt;Arachnophobia is two things rolled into one. I have tried to make installation a frictionless exercise so that you can get onto more important things in your day.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;An ASP.Net HttpHandler&lt;/strong&gt; that implements a robots.txt file with a disallow all telling spiders to stay away.&lt;/p&gt;  &lt;pre class="code"&gt;User-agent: *
Disallow: /&lt;/pre&gt;

&lt;p&gt;This means that when a search engine spider comes to visit your site, if they aren’t evil spiders and abide by the “non-standardised” standard for &lt;a href="http://www.robotstxt.org/orig.html"&gt;robots.txt&lt;/a&gt; (there is no actual standards body for this, as it was simply agreed in June 1994 by members of the robots mailing list), they will attempt to download the file /robots.txt from the root of you&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An ASP.Net HttpModule&lt;/strong&gt; that adds the &lt;a href="http://code.google.com/web/controlcrawlindex/docs/robots_meta_tag.html"&gt;Google/Yahoo X-Robots-Tag&lt;/a&gt; header to every asset/page request.&lt;/p&gt;

&lt;pre class="code"&gt;HTTP/1.1 200 OK
Date: Tue, 25 May 2010 21:42:43 GMT
&lt;em&gt;(…)&lt;/em&gt;
&lt;strong&gt;X-Robots-Tag: noindex&lt;/strong&gt;
&lt;em&gt;(…)&lt;/em&gt;&lt;/pre&gt;

&lt;h3&gt;What it is not&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Let’s be clear – this is a beta project so if it eats your babies, I take no responsibility. This carries the “works on my machine” badge, so Buyer beware…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Arachnophobia doesn’t actually &lt;strong&gt;stop&lt;/strong&gt; spiders from indexing your site – your site will still be accessible in a web browser for any passer-by to see. Relying on this “security through obscurity” approach should not be considered best practice if you want to&lt;em&gt; hide&lt;/em&gt; your site.&lt;/p&gt;

&lt;p&gt;What Arachnophobia does do however, is easily &lt;em&gt;setup a robots.txt&lt;/em&gt; file for your site and also add an &lt;em&gt;http header to each page request &lt;/em&gt;telling spiders “please don’t index my site” – this is a passive approach though and will only work for the main search engines such as Yahoo, Bing, Google etc. There are still plenty of bad web spiders crawling the web that disobey this form of “request” to not index.&lt;/p&gt;

&lt;p&gt;For mission critical web applications that you want to show to a client you should at the very least setup your webserver to only serve requests to a white list of IP addresses (i.e. you and your client’s IP addresses) or hide the site behind some form of authentication.&lt;/p&gt;

&lt;h3&gt;Why do you care?&lt;/h3&gt;

&lt;p&gt;You may be left thinking that you could easily add a &lt;em&gt;robots.txt&lt;/em&gt; and the specific header to IIS manually easily, so what is the point?&lt;/p&gt;

&lt;p&gt;The idea behind Arachnophobia is threefold:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When you need to add robots.txt and http headers nearly instantly using Nuget (and then take them away just as easily).&lt;/li&gt;

  &lt;li&gt;When you want to apply these features to a whole server at once (the binary is signed and can be added to the GAC and i have a setup project in the works to make this even easier).&lt;/li&gt;

  &lt;li&gt;In future i will be adding more features that will extend this functionality (such as hard blocking based on user agents etc).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Where can I get it&lt;/h3&gt;

&lt;p&gt;Add it to your ASP.Net website using the NuGet package manager:&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/f9f7f84d-efc4-4433-aa83-194d602c2312_image_e8f01c9c-60f2-4272-89a6-030dd59f9c76.png" width="458" height="71" /&gt;&lt;/p&gt;

&lt;p&gt;Or download from NuGet &lt;a href="https://nuget.org/packages/Arachnophobia"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Download the &lt;a href="https://github.com/dougrathbone/Arachnophobia/tree/master/Source"&gt;Source Code from GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the &lt;a href="https://github.com/dougrathbone/Arachnophobia/tree/master/Binaries"&gt;Binaries from GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Installation&lt;/h3&gt;

&lt;p&gt;If you download the Binaries and want to install it yourself manually you simply need to follow the bouncing ball:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Reference the “Arachnophobia.IIS.dll” Binary in your ASP.net website&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Add the Http Handler and Http Module sections to your web.config&lt;/em&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AracnophobiaHeaderModule&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Arachnophobia.IIS.RobotHeaderModule&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpHandlers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;path&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;robots.txt&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;verb&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;*&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Arachnophobia.IIS.RobotsTxtHandler&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;httpHandlers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.webServer&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;validation &lt;/span&gt;&lt;span style="color: red"&gt;validateIntegratedModeConfiguration&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;modules &lt;/span&gt;&lt;span style="color: red"&gt;runAllManagedModulesForAllRequests&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AracnophobiaHeaderModule&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Arachnophobia.IIS.RobotHeaderModule&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;preCondition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;integratedMode&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;modules&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;handlers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;add &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AracnophobiaRobotsTxt&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;path&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;robots.txt&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;verb&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;*&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Arachnophobia.IIS.RobotsTxtHandler&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;preCondition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;integratedMode&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;handlers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.webServer&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rXWNeQoibmSwKeZG5BHIgomh0HY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rXWNeQoibmSwKeZG5BHIgomh0HY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rXWNeQoibmSwKeZG5BHIgomh0HY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rXWNeQoibmSwKeZG5BHIgomh0HY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=xlZPDkMs_OY:tDG9uJD_4tk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=xlZPDkMs_OY:tDG9uJD_4tk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=xlZPDkMs_OY:tDG9uJD_4tk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=xlZPDkMs_OY:tDG9uJD_4tk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/yjfSdWLQHTI" height="1" width="1"/&gt;</description><pubDate>1/18/2012 9:46:27 PM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/01/18/arachnophobia--spider-spider-go-away-come-again-another-day</feedburner:origLink></item><item><title>8 Must-Have Tools for Windows Phone 7 Development</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/2mJ8rwAzl-Q/8-musthave-tools-for-windows-phone-7-development</link><description>&lt;p&gt;After developing Windows Phone 7 applications in my spare time over the last year, I've collected an assortment of tools that make developing apps so much easier than when I first jumped in to Silverlight/Windows Phone 7 development. I only wish I'd know about them all when I first started down the Windows Phone 7 path. Whether you are just starting out or have been developing Windows Phone 7 apps for a while now, there’s something here for everyone. &lt;/p&gt;  &lt;h3&gt;Silverlight Spy&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/2c9ecb99-9a6d-493f-9726-8ad6a69441b0_image_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 10px 0px 10px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/051326ce-c7de-41f8-8767-9d6a975148dc_image_thumb.png" width="354" height="194" /&gt;&lt;/a&gt;This is simply a &lt;em&gt;must have&lt;/em&gt; for Windows Phone 7 development. Silverlight Spy is many things, but the easiest way of thinking about it is as a &lt;em&gt;Firebug&lt;/em&gt; replacement for Silverlight/Windows Phone 7. &lt;/p&gt;  &lt;p&gt;With &lt;a href="http://firstfloorsoftware.com/silverlightspy/" target="_blank"&gt;Silverlight Spy&lt;/a&gt; you can run your Windows Phone 7 application and make design/layout changes &lt;em&gt;in real-time&lt;/em&gt; and see those changes before your very eyes. Combine this with the &lt;a href="http://www.jeff.wilcox.name/2011/10/metrogridhelper/" target="_blank"&gt;Metro Grid Helper&lt;/a&gt; class from &lt;a href="https://twitter.com/jeffwilcox" target="_blank"&gt;Jeff Wilcox&lt;/a&gt; so that you can easily visualise the Metro design guidelines and make changes on the fly and you have an amazing combination! &lt;/p&gt;  &lt;p&gt;Unlike Expression Blend (and more like Firebug), you can simply select an element in your control tree and make those “just a little bit to the left” tweaks. You’ll note from my example image on the right of my Google Analytics app &lt;a href="http://www.windowsphone.com/en-US/apps/384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt; that it even highlights the control you have selected on the emulator screen. &lt;/p&gt;  &lt;p&gt;It also have a built in Isolated Storage viewer, Screen shot tool, Resource viewer and XAP package explorer. &lt;/p&gt;  &lt;p&gt;The licensing for Silverlight Spy has two options, a FREE limited version that doesn’t support Windows Phone 7, and a personal license for 69 euro. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://firstfloorsoftware.com/silverlightspy/"&gt;http://firstfloorsoftware.com/silverlightspy/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In a word – &lt;strong&gt;Priceless&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;I will do a more detailed post on Silverlight Spy soon. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Isolated Storage Explorer &lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/568c8065-2103-4b2f-b76f-7523c9df560a_image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/20026a08-efd7-4565-9443-735e6f52a0c5_image_thumb_1.png" width="354" height="223" /&gt;&lt;/a&gt;The Isolated Storage Explorer project over on CodePlex is an amazing freebie extension for your Windows Phone 7 development ‘getup’.&lt;/p&gt;  &lt;p&gt;In very basic terms it allows you to copy the Isolated Storage for your Windows Phone 7 application to a local folder so that you can view/edit etc. the files that are stored on your device – you can then copy these files &lt;em&gt;back onto your device&lt;/em&gt; allowing you to easily upload sample data to test certain situations that can be a bit harder such as large asset/image libraries, corrupted/invalid serialized data and performance issues from opening/saving overly large files.&lt;/p&gt;  &lt;p&gt;This tool has helped me troubleshoot a number of weird serialization issues I've had in the past, and with the addition of &lt;em&gt;Background Agents&lt;/em&gt; in Windows Phone 7.1 SDK its been a priceless tool for helping troubleshoot/view activity logs on my device during testing.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://istool.codeplex.com/"&gt;http://istool.codeplex.com/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Silverlight Toolkit&lt;/h3&gt;  &lt;p&gt;The Silverlight Toolkit is a package of controls that extend the Windows Phone 7 SDK and released under the Microsoft Public License. &lt;/p&gt;  &lt;p&gt;It is filled with a number of controls that are really missed in the base SDK (High Performance Progress Bar anyone?).&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;AutoCompleteBox &lt;/li&gt;    &lt;li&gt;DateTimeConverters &lt;/li&gt;    &lt;li&gt;DateTimePickers &lt;/li&gt;    &lt;li&gt;ExpanderView &lt;/li&gt;    &lt;li&gt;HeadersItemsControl &lt;/li&gt;    &lt;li&gt;HubTile &lt;/li&gt;    &lt;li&gt;Input &lt;/li&gt;    &lt;li&gt;ListPicker &lt;/li&gt;    &lt;li&gt;LocalizedResources &lt;/li&gt;    &lt;li&gt;LongListSelector &lt;/li&gt;    &lt;li&gt;MultiselectList &lt;/li&gt;    &lt;li&gt;PhoneTextBox &lt;/li&gt;    &lt;li&gt;Tilt &lt;/li&gt;    &lt;li&gt;ToggleSwitch &lt;/li&gt;    &lt;li&gt;Transitions &lt;/li&gt;    &lt;li&gt;WrapPanel &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A number of these you simply can’t get by without – the WrapPanel and DateTimePickers are definitely in this group.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://silverlight.codeplex.com/"&gt;http://silverlight.codeplex.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Portable Class Library project template&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/af4c97fb-fa40-426d-a5ae-a67e8f74b774_image_7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/56f3e89a-8533-4c2c-859d-66d11b66c166_image_thumb_2.png" width="354" height="220" /&gt;&lt;/a&gt;Most Windows Phone 7 apps end up having web services/websites/windows applications that sit side-by-side with them in a solution. Often this leads to code duplication as you keep your common classes in more than one place and struggle to keep them up to date/unit test them.&lt;/p&gt;  &lt;p&gt;The Portable Class Library Visual Studio add-on solves this by offering a class library project type that is compatible with any .Net project (ASP.Net, WPF, Silverlight, XNA). I’ve also tested this in multiple build-server environments without problem.&lt;/p&gt;  &lt;p&gt;Why this isn’t included as part of Visual Studio out-of-the-box we’ll never know.&lt;/p&gt;  &lt;p&gt;I’ve used this in nearly every one of my Windows Phone 7 Projects – I highly recommend it.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981"&gt;http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;High Performance Progress Bar&lt;/h3&gt;  &lt;p&gt;This is now included in the Mango version of the Silverlight Toolkit, but was originally created by Jeff Wilcox from the Windows Phone 7 team. &lt;/p&gt;  &lt;p&gt;In simple terms if you use the Progress Bar control in &lt;em&gt;Indeterminate&lt;/em&gt; mode (i.e. never ending a-synch waiting) in your Windows Phone 7 app, your Progress Bar is being a complete performance hog – the problem is more finicky in that you will only notice this problem once you’ve actually deployed your app to a &lt;em&gt;real device&lt;/em&gt; as it runs fine in the emulator. &lt;/p&gt;  &lt;p&gt;The problem is caused by the out-of-the-box Progress Bar control using the Compositor thread exclusively for it’s animation instead of the UI thread.&lt;/p&gt;  &lt;p&gt;In the early days of Windows Phone development this was a gripe that a number of developers moaned about until Jeff came out with this replacement control.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://silverlight.codeplex.com/"&gt;http://silverlight.codeplex.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.jeff.wilcox.name/2010/08/performanceprogressbar/"&gt;http://www.jeff.wilcox.name/2010/08/performanceprogressbar/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Metro Grid Helper&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/538d7b99-f15a-4c8e-9742-7879bfad8db4_image_9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/17e412b6-9c84-47eb-b3f1-819cf6abd2ae_image_thumb_3.png" width="304" height="281" /&gt;&lt;/a&gt;Another &lt;em&gt;must have&lt;/em&gt; tool from Microsoft/Jeff Wilcox is the Metro Grid Helper.&lt;/p&gt;  &lt;p&gt;The Windows Phone 7 team have definitely created something amazing with the Metro design styling that Windows Phone 7 comes with, but like nearly all design styles Metro looks most polished when everything is perfectly in symmetry.&lt;/p&gt;  &lt;p&gt;For Metro this means &lt;a href="http://www.jeff.wilcox.name/2011/03/metro-design-guide-v1/"&gt;12px spacing everywhere, run on button text, and overall a simple rule of living and dying&lt;/a&gt; by &lt;em&gt;alignment&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;The tiny Nuget package &lt;em&gt;MetroGridHelper&lt;/em&gt; (its only a single class!) serves these needs perfectly by simply overlaying a 24px x 24px grid with 12px spacing over your app to make fixing alignment issues and conforming to the &lt;a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2010/03/18/windows-phone-7-series-ui-design-amp-interaction-guide.aspx"&gt;Windows Phone 7 Design Guidelines&lt;/a&gt; dead simple.&lt;/p&gt;  &lt;p&gt;Jeff released the first version of this at the end of 2011 and it hasn’t left my toolbox since.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/a3e250bb-8c91-4888-b470-494bfd9dd59f_image22.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/08ffcf2e-13d5-42da-bc23-037bf19bd771_image22_thumb.png" width="350" height="50" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://nuget.org/packages/MetroGridHelper"&gt;http://nuget.org/packages/MetroGridHelper&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Windows Phone Test Project&lt;/h3&gt;  &lt;p&gt;The unit testing tools available to Windows Phone 7 developers aren’t really there at all out-of-the-box. &lt;/p&gt;  &lt;p&gt;A fellow Aussie &lt;a href="http://jake.ginnivan.net/"&gt;Jake Ginnivan&lt;/a&gt;, noted this and created a project template that allows you to use either the &lt;a href="http://archive.msdn.microsoft.com/silverlightut"&gt;Silverlight Unit Testing Framework&lt;/a&gt; or the &lt;a href="http://nuget.org/packages/WindowsPhoneEssentials.Testing"&gt;WindowsPhoneEssentials.Testing Framework&lt;/a&gt; to unit test your Windows Phone 7 code.&lt;/p&gt;  &lt;p&gt;I am still yet to see many developers discussing Unit Testing in the Windows Phone 7 world – mostly because a lot of apps written for the Windows Phone 7 platform are either simple or are written by people new to the .Net space. &lt;/p&gt;  &lt;p&gt;I think this is a bit of a shame as i think the MVVM patterns works &lt;em&gt;really well&lt;/em&gt; with unit testing, so there should definitely be more engagement in this space over the coming year (hopefully).&lt;/p&gt;  &lt;p&gt;Check it out in either the Extension Manager inside Visual Studio 2010 or online:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/6819514d-4bd6-4f31-a231-48c6530ed03b?SRC=VSIDE"&gt;http://visualstudiogallery.msdn.microsoft.com/6819514d-4bd6-4f31-a231-48c6530ed03b?SRC=VSIDE&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Emulator Skins&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/47a1c4af-1220-4629-b031-6c61bc37a722_image_11.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/92316c29-f36a-4366-ac23-9bf75893016e_image_thumb_4.png" width="354" height="250" /&gt;&lt;/a&gt;This last one isn’t really &lt;em&gt;essential&lt;/em&gt; but if you are spending a lot of time looking the Windows Phone 7 Emulator you’ll most probably be getting a little sick of the basic “looks like no Windows Phone I've ever seen” skin on your emulator.&lt;/p&gt;  &lt;p&gt;This can be easily replaced by any number of other phone skins – many from phones you’ve seen your local Windows Phone 7 owners toting, and even other un-released or soon to be released phones such as the new Lumia 800.&lt;/p&gt;  &lt;p&gt;The Windows Phone 7 Emulator Skin Switch has 25 skins to try.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://wp7emuskinswitcher.codeplex.com/"&gt;http://wp7emuskinswitcher.codeplex.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Jeff Wilcox (tell me about it… it’s like this guy has nothing better to do than create awesome stuff for WP7 devs) has also created a single skin based on the device shown throughout the MSDN site:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.jeff.wilcox.name/2011/12/my-new-windows-phone-emulator-theme/"&gt;http://www.jeff.wilcox.name/2011/12/my-new-windows-phone-emulator-theme/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2FFcwKOmMyAI2LBXreS6x5rlJq0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2FFcwKOmMyAI2LBXreS6x5rlJq0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2FFcwKOmMyAI2LBXreS6x5rlJq0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2FFcwKOmMyAI2LBXreS6x5rlJq0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0djFFX4oOG8:Nsgr5hegTP4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0djFFX4oOG8:Nsgr5hegTP4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=0djFFX4oOG8:Nsgr5hegTP4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=0djFFX4oOG8:Nsgr5hegTP4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/2mJ8rwAzl-Q" height="1" width="1"/&gt;</description><pubDate>1/23/2012 5:33:41 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/01/23/8-musthave-tools-for-windows-phone-7-development</feedburner:origLink></item><item><title>InTheKnow Google Analytics Version 1.8 Released for Windows Phone 7</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/wssDnuVI_DA/intheknow-google-analytics-version-18-for-windows-phone-7</link><description>&lt;p&gt;Today marks the release of &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt; Google Analytics version 1.8 for Windows Phone 7 – there is a lot of little tweaks that have come about during the creation of this next version, and I'm excited that it is out there and getting great feedback. I spent a large chunk of the downtime in my Christmas break working on InTheKnow, so it is great to finally release the next version. If you haven’t tried the app, and are looking for and easy way to check your website’s Google Analytics on your Windows Phone 7 device, &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;check it out&lt;/a&gt; – the trial is free.&lt;/p&gt; &lt;p&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/24b6314f-9717-47a3-a408-4d936930eb9c_image_a04fd0be-a502-4f35-bc1e-ed8fbed19876.png" width="125" height="240"&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/26a87651-4a91-4237-97cf-a36ec89139e4_image_003b731f-00ba-47df-8114-bc2cf2ce0581.png" width="125" height="240"&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/1228e371-df4b-4ca7-8d4f-743ee4a22fe9_image_795c7a0b-21d4-4bbc-a4f7-eb84c9d337e7.png" width="125" height="240"&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/684e00f5-548d-4282-8b92-f2eef25fbfa9_image_0f775db7-b627-4641-886b-9182f25bdbb7.png" width="125" height="240"&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/e325db49-5e26-4163-9e43-e81ab3a84e9b_image_6dc48ee0-49f8-48ca-be9c-309988482170.png" width="125" height="240"&gt;&lt;/p&gt; &lt;p&gt;Below is a list of a number of the added features and changes in the update.&lt;/p&gt; &lt;h3&gt;Mango support for Live Tiles&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;“… Time to cram that start page with some Tiles*…”&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;img style="margin: 0px 0px 0px 15px; display: inline; float: right" title="image" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/75cb275f-426f-4d4b-8b90-457a8c018454_image_a25587fd-03b1-4881-a34f-200e480ad432.png" width="125" height="240"&gt;You can now pin multiple Live Tiles to your device’s start screen.&lt;/p&gt; &lt;p&gt;I’ve seen how a lot of apps allow you to pin live tiles, but &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt; is slightly different in the fact that it’s main demographic (web developers looking for easy to access stats on their sites) often are complete ‘stat whores’ in the sense that they want to check the stats multiple times a day. &lt;/p&gt; &lt;p&gt;I am often no different, even if i haven’t posted a blog post in a couple of months or created a new site in a while – because of this character trait of mine i wanted to be able to pin not only &lt;em&gt;multiple sites&lt;/em&gt; but also &lt;em&gt;multiple time periods for multiple sites&lt;/em&gt;. &lt;/p&gt; &lt;p&gt;Now you don’t even need to open &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt; to know lots of different stats at the same time.&lt;/p&gt; &lt;p&gt;I have also added support for &lt;em&gt;back&lt;/em&gt; Live Tiles, with the addition of &lt;em&gt;bounce rate &lt;/em&gt;and &lt;em&gt;time on site&lt;/em&gt; to the stats you can see from each of your live tiles for the period.&lt;/p&gt; &lt;p&gt;* Live tiles require cellular data usage to update, pinning many live tiles will obviously increase your data usage – &lt;a href="http://en.wikipedia.org/wiki/Caveat_emptor" target="_blank"&gt;Caveat emptor&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;New report: Time on site&lt;/h3&gt; &lt;p&gt;&lt;img style="margin: 0px 0px 0px 15px; display: inline; float: right" title="image" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/20fc3f19-2ed8-4fa0-9cd1-11dd50da892f_image_2147b070-664e-4a85-82ac-6209f7cc2843.png" width="125" height="240"&gt;There are still a few key reports that I want to add to &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt; over time, so I'm excited to add &lt;strong&gt;Time on site&lt;/strong&gt; to the list of reports displayed in the app.&lt;/p&gt; &lt;p&gt;As your site grows, one of the key indicators that your visitors are engaged is the amount of time they spend interacting with your website. There is a good summary on why this doesn’t always show an absolute value over on the &lt;a href="http://webmasters.stackexchange.com/a/22778" target="_blank"&gt;Webmasters StackExchange&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Watch out for more reports to come.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;New polished look and feel&lt;/h3&gt; &lt;p&gt;I’ve learnt a lot about designing and building Windows Phone 7 applications since i first created &lt;a href="http://windowsphone.com/s?appid=384748cc-4e1c-e011-9264-00237de2db9e" target="_blank"&gt;InTheKnow&lt;/a&gt;, and therefore i felt that it was about time refreshing the layout and detail put into the finished product.&lt;/p&gt; &lt;p&gt;Jeff Wilcox has made it dead easy to make beautiful looking Windows Phone 7 apps by releasing both a &lt;a href="http://www.jeff.wilcox.name/2011/03/metro-design-guide-v1/" target="_blank"&gt;Metro Design Guide for developers&lt;/a&gt; and the &lt;a href="http://www.jeff.wilcox.name/2011/10/metrogridhelper/" target="_blank"&gt;MetroGridHelper&lt;/a&gt;, both of these helped a lot in polishing the app to where it is in this release.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Have your say&lt;/h3&gt; &lt;p&gt;Are you using InTheKnow? do you have some feedback you’d like to let me know about?&lt;/p&gt; &lt;p&gt;If so, why not &lt;a href="/me" target="_blank"&gt;shoot me an email&lt;/a&gt; telling me all about it – I'd love to know.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H9qCm5QeKT-pPg3fPM8Rninvn7o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H9qCm5QeKT-pPg3fPM8Rninvn7o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H9qCm5QeKT-pPg3fPM8Rninvn7o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H9qCm5QeKT-pPg3fPM8Rninvn7o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=Ahi-tLDcR54:syVLU95Id8g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=Ahi-tLDcR54:syVLU95Id8g:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=Ahi-tLDcR54:syVLU95Id8g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=Ahi-tLDcR54:syVLU95Id8g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/wssDnuVI_DA" height="1" width="1"/&gt;</description><pubDate>2/8/2012 3:26:08 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/02/08/intheknow-google-analytics-version-18-for-windows-phone-7</feedburner:origLink></item><item><title>DevOps DNS for Developers – Now There’s No Excuse Not To Know</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/uCEJVbJKqpI/devops-dns-for-developers-ndash-now-therersquos-no-excuse-not-to-know</link><description>&lt;p&gt;Over the years I have had the luck to work alongside many really smart, switched on people in the development community. I’ve learnt from them many intermediate and experienced programming skills. Generally when it comes understanding the very basis of how the internet functions using DNS, most of these very same experienced developers haven’t got a clue. I wrote this post to hopefully help pay back some of the awesome karma they&amp;nbsp; have earned helping me over the years, by teaching them something in return. Lets learn about DNS.&lt;/p&gt; &lt;p&gt;&lt;img style="margin: 10px 0px 10px 10px; display: inline; float: right" title="image" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/f2baaa2c-26e4-4d0c-8c1a-9d4519a86a1b_image_d771a9ac-db70-40c3-b6ef-42f056edca7a.png" width="170" height="240"&gt;DNS is a huge part of the inner workings of the internet. Web Developers spend a considerable amount of man hours a year ensuring the sites they build are fast and respond well to user interaction by setting up expensive CDN’s, recompressing images, minifying script files and much more – but what a lot of us don’t understand is that DNS server configuration can make a big difference to the speed of your site – hopefully at the end of this post you’ll feel empowered to get the most out of this part of your website’s configuration.&lt;/p&gt; &lt;p&gt;What I will cover in this post:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href="#howitworks"&gt;How the internet works from a Domain/DNS standpoint.&lt;/a&gt;  &lt;li&gt;&lt;a href="#toolsforthejob"&gt;Tools that you should use when investigating DNS problems or testing configuration.&lt;/a&gt;  &lt;li&gt;&lt;a href="#recordtypes"&gt;A basic overview of the main types of DNS records.&lt;/a&gt;  &lt;li&gt;&lt;a href="#domainsetup"&gt;Setting up a site from scratch.&lt;/a&gt;  &lt;li&gt;&lt;a href="#investigate"&gt;Investigating some common problems.&lt;/a&gt; &lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Why does DNS matter to you?&lt;/h2&gt; &lt;p&gt;Well it’s simple – if you are a developer it matters to you because:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You are a passionate developer, and therefore knowing this stuff is &lt;strong&gt;&lt;u&gt;your job&lt;/u&gt;&lt;/strong&gt;.  &lt;li&gt;You own a website, and up until now your webhost has taken care of your DNS for you – but you need to know what's going on in case something bad happens…  &lt;li&gt;Maybe the webhost you have allows you to manage your own DNS using a web interface, but you haven’t a clue what you are doing.  &lt;li&gt;The DNS that your webhost or ISP offers you is probably not the fastest – if your website grows over time, you probably want to setup your own DNS or manage it through a dedicated service such as &lt;a href="http://www.dnsmadeeasy.com/" target="_blank"&gt;DNSMadeEasy&lt;/a&gt;, &lt;a href="http://www.zoneedit.com" target="_blank"&gt;ZoneEdit&lt;/a&gt; or &lt;a href="http://dyn.com/dns/" target="_blank"&gt;DynDNS&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;a name="howitworks"&gt;&lt;/a&gt; &lt;h2&gt;First up: How the internet works (DNS)&lt;/h2&gt; &lt;p&gt;If you already know how this works feel free to step ahead.&lt;/p&gt; &lt;p&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a3da0d03-b76e-45bd-81c0-b098151b0670_image_3ce7ccf3-80f1-4607-bcf1-2fe07a0e9cc2.png" width="541" height="336"&gt;&lt;/p&gt; &lt;p&gt;In really simple terms, when you enter a URL and hit enter, apart from magical unicorns rendering the requested page in your browser window, the interwebs works kinda like this:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You want to visit to a domain name, so your PC first checks its internal DNS cache to see if it’s looked it up recently – if so it uses this record &lt;li&gt;Your PC then asks your DNS server (probably configured by your router or ISP when you first started your PC) for the IP address of the server hosting the domain name you want to visit.  &lt;li&gt;Your ISP’s DNS server looks up the &lt;a href="http://www.root-servers.org/" target="_blank"&gt;root DNS servers for the world&lt;/a&gt; to find out who takes care of the DNS configuration for the domain you want to visit.  &lt;li&gt;Your ISP’s DNS server then asks this a&lt;em&gt;uthorative&lt;/em&gt; DNS server for the domain name you want’s IP information, fetches it, caches it, and then returns it to your PC.  &lt;li&gt;Your browser connects to this IP address and asks for a web page. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;There are a number of different scenarios that play a role in special circumstances with the above but I'm not really going to cover &lt;strong&gt;everything&lt;/strong&gt; in this post.&lt;/p&gt; &lt;h3&gt;What DNS does do:&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Converts hostnames to IP addresses.  &lt;li&gt;Stores mail delivery information for a domain.  &lt;li&gt;Stores miscellaneous information against a domain name (TXT records). &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;What DNS doesn’t/cannot do&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Redirects users to a different server/site.  &lt;li&gt;Configure which port the client is connecting to (not entirely true; &lt;a href="http://en.wikipedia.org/wiki/SRV_record"&gt;SRV records&lt;/a&gt; are used for protocol/port mappings for &lt;em&gt;services&lt;/em&gt;).&lt;/li&gt;&lt;/ul&gt;&lt;a name="toolsforthejob"&gt;&lt;/a&gt; &lt;h2&gt;Tools for the Job&lt;/h2&gt; &lt;p&gt;One of the coolest things about the tools you’ll need for this blog post, is where I tell you that independent of which operating system you are using, you almost certainly have everything you need to query and test the DNS configuration of your website installed right now without you even knowing&lt;/p&gt; &lt;p&gt;The Swiss Army Knife of DNS inspection is the command line tool &lt;a href="http://en.wikipedia.org/wiki/Nslookup" target="_blank"&gt;NSLOOKUP&lt;/a&gt;. This is installed by default in nearly &lt;em&gt;every OS you’ll ever need it on&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://technet.microsoft.com/en-us/library/bb490721.aspx" target="_blank"&gt;NSLOOKUP on Windows&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://linux.die.net/man/1/nslookup" target="_blank"&gt;NSLOOKUP on Unix/Linux/Mac OSX&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Another cool thing the usage is the same on most platforms as well.&lt;/p&gt; &lt;p&gt;To run NSLOOKUP simply open a terminal/command prompt and type &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;nslookup&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/035141bc-c76a-4030-92cf-7aeac036a7d2_image_15aa9acd-e42b-403d-823b-7cd4856006ac.png" width="454" height="231"&gt;&lt;/p&gt; &lt;p&gt;The first thing you’ll notice about the pic above is that the first thing NSLOOKUP tells me upon launch is the current DNS server that it will use for its lookups.&lt;/p&gt; &lt;p&gt;By default NSLOOKUP will use your current machine’s DNS settings for its DNS lookups. This can sometimes give you different results from &lt;em&gt;the rest of the world&lt;/em&gt; as your internal DNS at your place of work/ISP may be returning different results so they can route, say your office mail, to the internal mail server IP rather than the external internet/DMZ IP address.&lt;/p&gt; &lt;p&gt;Lets change this to use &lt;a href="http://code.google.com/speed/public-dns/" target="_blank"&gt;Google’s global DNS server&lt;/a&gt; to get a better &lt;em&gt;global view&lt;/em&gt; (what others see when they surf the web outside my network) on our DNS queries, by typing;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;server 8.8.8.8&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now if I query this blog’s domain name “&lt;em&gt;diaryofaninja.com.”&lt;/em&gt; &lt;u&gt;(ensure you place the additional period on the end of this query to avoid any internal DNS suffixes to be added)&lt;/u&gt; I should get back the &lt;strong&gt;&lt;em&gt;A record&lt;/em&gt;&lt;/strong&gt; for my domain; (A records are the default query type used by NSLOOKUP – I discuss DNS record types further in this post below).&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/f30abe77-bd67-4b13-b32a-1a33d8e43288_image_a4e960d1-a0c0-4c97-9f3b-4b6ca11871cd.png" width="454" height="231"&gt;&lt;/p&gt;&lt;a name="recordtypes"&gt;&lt;/a&gt; &lt;h2&gt;An overview of common DNS record types&lt;/h2&gt; &lt;p&gt;Below is a simple overview of all the common types of DNS records and some example scenarios.&lt;/p&gt; &lt;p&gt;All records usually share the following common properties:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt; – this is usually the contents of the records. If it is an A record this is the IP address for that A record&lt;/p&gt; &lt;p&gt;&lt;strong&gt;TTL&lt;/strong&gt; – this is the “Time To Live” in seconds for a DNS record and basically means that DNS Clients of Servers accessing the requested record should not cache the record any longer than this value. If this value is set to &lt;strong&gt;3600&lt;/strong&gt; this means to cache the returned record’s value for an hour (these values are usually the reason that IT people talk about DNS changes taking “24-48 hours” as these values are usually set quite high on hostnames that are quite static so that they offer the best performance by being kept in cache.&lt;/p&gt; &lt;h3&gt;SOA (Start of Authority) records&lt;/h3&gt; &lt;p&gt;SOA records (start of authority records) are the root of your domain’s registration. SOA records are created by your domain name registrar in the parent domain’s DNS servers (in the case of a .com domain the SOA record is created in the DNS servers for the .com root domain. In an SOA record the hostnames or IP addresses of your domain’s DNS servers are stored. These tell the internet’s root DNS servers (mother ship DNS servers) where to ask for the rest of your domain’s DNS configuration (such as A, MX and TXT records). When a client (a web browser, a mail server, an FTP client etc.) wants to connect to part of your website, it asks the locally configured DNS server for the record –&amp;nbsp; the server in turn looks for the SOA records for your domain so it knows which DNS server to ask about it.&lt;/p&gt; &lt;p&gt;Consider these records as the source of “which DNS server stores all the information about the website I want to look up”.&lt;/p&gt; &lt;h3&gt;Hostname (A and CNAME) records&lt;/h3&gt; &lt;p&gt;&lt;strong&gt;A records&lt;/strong&gt; store information about a &lt;a href="http://en.wikipedia.org/wiki/Hostname" target="_blank"&gt;hostname&lt;/a&gt; record for your domain name. These list the IP address that a client should talk to when using a certain hostname.&lt;/p&gt; &lt;p&gt;If you had an address of &lt;a href="http://mywebsite.examplecompany.com"&gt;http://mywebsite.examplecompany.com&lt;/a&gt; into your web browser this would refer to the &lt;strong&gt;A record “&lt;/strong&gt;&lt;em&gt;mywebsite&lt;/em&gt;” on the domain “&lt;em&gt;examplecompany.com&lt;/em&gt;”.&lt;/p&gt; &lt;p&gt;If you have &lt;em&gt;multiple &lt;/em&gt;A records with the same hostname, clients will receive a list of all the records. The order of this list will change with iterate each time you query the DNS server – this is called &lt;a href="http://en.wikipedia.org/wiki/Round-robin_DNS"&gt;&lt;em&gt;round-robin DNS&lt;/em&gt;&lt;/a&gt; and it a simple way to spread load across multiple servers &lt;em&gt;.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AAAA records&lt;/strong&gt; are the same as &lt;strong&gt;A records&lt;/strong&gt;, only they stores the 128bit IPv6 address of a server instead of the IPv4 IP address – as the world shifts to using IPv6 these records will gain more relevance, but if your webhost supports IPv6 its worth setting these records up now, so that any visitors using IPv6 can access your website.&lt;/p&gt; &lt;p&gt;A &lt;strong&gt;CNAME record&lt;/strong&gt; (Canonical name) is basically&amp;nbsp; an alias for an &lt;strong&gt;A record&lt;/strong&gt;. This tells whoever is asking, that the DNS information for the requested hostname is stored in another record somewhere else on the internet. This other record might not even be on the same domain name or on the same DNS server. &lt;strong&gt;CNAME’s &lt;/strong&gt;are very powerful as they allow you simplify your domains DNS records by centralising the information somewhere else. ISPs and webhosts commonly use &lt;strong&gt;CNAMEs&lt;/strong&gt; to centralise the DNS configuration storage for things like mail or web server’s by allowing you to keep all the configuration details on a parent domain name.&lt;/p&gt; &lt;p&gt;It is important to note that &lt;strong&gt;root records&lt;/strong&gt; for a domain name (I.e the empty A record for &lt;em&gt;mydomain.com)&lt;/em&gt; &lt;strong&gt;&lt;u&gt;cannot be a CNAME&lt;/u&gt;&lt;/strong&gt;. The simple hard and fast reason why, is that CNAME’s cannot live on the same node in a DNS forest as any other type of record – because the very nature of a CNAME record defines that all configuration for that node is stored somewhere else, and given you store other information at the root of your domain other than your A record (MX records for mail etc.) this would break every other record’s functionality. This is mentioned specifically in the &lt;a href="http://tools.ietf.org/html/rfc1034"&gt;RFC for DNS, section 3.6.2&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;An example of CNAME usage, is when most webhosting company web servers have a hostname such as &lt;strong&gt;web0234.mywebhost.com&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;When setting up your website, your webhost might for instance make the “&lt;em&gt;www.yourwebsite.com&lt;/em&gt;&lt;strong&gt;”&lt;/strong&gt; record for your website a&lt;strong&gt; CNAME&lt;/strong&gt; that has the value &lt;em&gt;&lt;strong&gt;“&lt;/strong&gt;web0234.mywebhost.com&lt;strong&gt;”&lt;/strong&gt;&lt;/em&gt; so that when trying to access “&lt;em&gt;www.yourwebsite.com” &lt;/em&gt;DNS clients look up the IP address for “&lt;em&gt;web0234.mywebhost.com”.&lt;/em&gt; This makes their life easier if the IP address for this web server changes, as they only have to update a single DNS record, instead of updating &lt;em&gt;all&lt;/em&gt; their clients DNS records.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;To reiterate this to make it crystal clear: &lt;br&gt;CNAME’s are &lt;u&gt;not&lt;/u&gt; a redirection. They are a reference pointer for a hostname. All they tell DNS clients, is that the configuration information for the hostname being queried is &lt;strong&gt;&lt;u&gt;the same as can be found by querying the other hostname.&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;Illustration – Visiting a website&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In the case that you want to visit &lt;em&gt;www.google.com&lt;/em&gt; your computer does the following:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Using the local machine’s DNS client your operating system talks to the locally configured DNS server for your local network/ISP’s network.  &lt;li&gt;This DNS server inturn looks up the DNS server for &lt;em&gt;&lt;strong&gt;google.com&lt;/strong&gt;&lt;/em&gt; by first looking up the &lt;strong&gt;&lt;em&gt;SOA record&lt;/em&gt;&lt;/strong&gt; for &lt;em&gt;&lt;strong&gt;google.com&lt;/strong&gt;&lt;/em&gt; and then connecting to the DNS server listed.  &lt;li&gt;Your local DNS server then asks the DNS server for &lt;strong&gt;google.com&lt;/strong&gt; for the &lt;strong&gt;&lt;em&gt;A record&lt;/em&gt;&amp;nbsp;&lt;/strong&gt;listed for &lt;strong&gt;&lt;em&gt;www – &lt;/em&gt;&lt;/strong&gt;the &lt;strong&gt;&lt;em&gt;google.com&lt;/em&gt;&lt;/strong&gt; DNS server will return an IP address for &lt;strong&gt;www.google.com.&lt;/strong&gt; Your ISP or local network’s DNS server, along with returning it to you, will then cache this record for as long as the TTL (time to live) property of the record says.  &lt;li&gt;Your browser then connects to this returned IP address listed on port 80 and asks for the web page. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;All of the above happens in milliseconds – but you can understand that if the &lt;em&gt;google.com&lt;/em&gt; DNS server is slow in responding this negatively affects your browsing experience.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;A records and CNAME records have a&lt;strong&gt; TTL (Time To Live)&lt;/strong&gt; property to indicate how long they can be cached for.&lt;/p&gt; &lt;h3&gt;Mail (MX)&lt;/h3&gt; &lt;p&gt;&lt;strong&gt;MX records &lt;/strong&gt;are the internets way of telling mail where to be delivered. They list the hostname or IP address of the mail server that handles mail for a given domain name. If a mail server is looking to deliver mail to “&lt;em&gt;examplecompany.com&lt;/em&gt;” it will look up the MX record for this domain.&lt;/p&gt; &lt;p&gt;MX records have both a &lt;strong&gt;TTL (Time To Live) &lt;/strong&gt;and a &lt;strong&gt;Priority&lt;/strong&gt; (a weighting to give the order in which they should be looked up).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Illustration – Sending an e-mail to a friend&lt;/strong&gt; &lt;/p&gt; &lt;p&gt;In the case that you send an email to your friend at &lt;strong&gt;&lt;em&gt;&lt;a href="mailto:myfriend@otherexamplecompany.com"&gt;myfriend@otherexamplecompany.com&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; your local SMTP mail server (usually at your ISP) does the following:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Your mail server connects to its local network/ISP’s DNS server and asks for the MX record for &lt;strong&gt;otherexamplecompany.com.&lt;/strong&gt;  &lt;li&gt;Your local DNS server or ISP’s DNS server looks up the &lt;strong&gt;&lt;em&gt;SOA record&lt;/em&gt;&lt;/strong&gt; for &lt;strong&gt;&lt;em&gt;otherexamplecompany.com&lt;/em&gt;&lt;/strong&gt; and then connects to the DNS server listed.  &lt;li&gt;It asks for the &lt;strong&gt;MX records&lt;/strong&gt; for this domain and is returned a list of hostnames.  &lt;li&gt;it grabs the first hostname from the list (order in ascending order by Priority), runs a second query for the IP address of this mail server and returns this IP address to your mail server.  &lt;li&gt;your mail server then connects to this IP address on the SMTP TCP port 25 and delivers your mail. &lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Text Records (TXT)&lt;/h3&gt; &lt;p&gt;TXT records are a powerful addition to the DNS standard that allow the storage of miscellaneous information for a hostname. Many web developers, system admins and the like use TXT records for the storage of information such as &lt;a href="http://www.diaryofaninja.com/blog/2011/09/27/what-all-good-web-developers-should-know-about-sending-email" target="_blank"&gt;SPF records&lt;/a&gt; and &lt;a href="http://www.diaryofaninja.com/blog/2011/11/16/when-you-really-need-your-email-delivered-ndash-signing-your-mail-using-domain-keysdkim" target="_blank"&gt;DKIM public keys&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;TXT records have a&lt;strong&gt; TTL (Time To Live)&lt;/strong&gt; property to indicate how long they can be cached for.&lt;/p&gt; &lt;h3&gt;Name Server Records (NS)&lt;/h3&gt; &lt;p&gt;Name Server Records are placed in your domain’s DNS when you wish to store the configuration of part of your domain’s DNS on a separate DNS server. This can be very handy if you want to give control of a subdomain to another person/entity.&lt;/p&gt; &lt;p&gt;i.e. my site is &lt;strong&gt;&lt;em&gt;www.widgetsareus.com&lt;/em&gt;&lt;/strong&gt; and I manage all of the DNS for this domain, but I would like &lt;strong&gt;&lt;em&gt;support.widgetsareus.com&lt;/em&gt;&lt;/strong&gt; and any &lt;u&gt;&lt;em&gt;child sub domains&lt;/em&gt;&lt;/u&gt; of this domain to be managed by the company we outsource all of our customer support to – therefore I have setup an NS record for &lt;strong&gt;&lt;em&gt;support.widgetsareus.com&lt;/em&gt;&lt;/strong&gt; to point at our support partner’s DNS servers.&lt;/p&gt;&lt;a name="domainsetup"&gt;&lt;/a&gt; &lt;h2&gt;Setting up a domain from scratch&lt;/h2&gt; &lt;p&gt;If you are setting up a domain you’ve just purchased from scratch you’ll need to do the following:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Setup your website (A records)&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Setup a DNS server to store the configuration for &lt;strong&gt;yourdomain.com&lt;/strong&gt; &lt;br&gt;This might be at your webhost, or might be a third party service such as &lt;a href="http://www.dnsmadeeasy.com/" target="_blank"&gt;DNSMadeEasy&lt;/a&gt;, &lt;a href="http://www.zoneedit.com" target="_blank"&gt;ZoneEdit&lt;/a&gt; or &lt;a href="http://dyn.com/dns/" target="_blank"&gt;DynDNS&lt;/a&gt;.  &lt;li&gt;Set the Nameserver SOA records for your domain name to the above DNS server’s IP address or hostname (at your domain registrar)  &lt;li&gt;Create a new &lt;strong&gt;root &lt;/strong&gt;record to point at your webserver’s IP address (this is simply an A record with an &lt;em&gt;empty hostname)&lt;/em&gt; in your domain name’s DNS forest.  &lt;li&gt;Create a new &lt;strong&gt;www&lt;/strong&gt; A record that points at your webserver’s IP address in your domain’s DNS server  &lt;li&gt;Setup your webserver’s website to listen for the &lt;strong&gt;host-header&lt;/strong&gt; of your domain name (IIS calls this a “binding”).  &lt;li&gt;Test your DNS as below.  &lt;li&gt;Try and access your site in a web browser. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Testing your website’s A record&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In a command prompt/terminal type &lt;em&gt;NSLOOKUP&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Enter “&lt;em&gt;yourdomainname.com.”&lt;/em&gt; (including the extra period on the end) and hit enter&lt;/p&gt; &lt;p&gt;Check that the returned record value/IP address is that of your web server.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/45e8bbae-0dd6-41db-a92a-541a783ea1bf_image_6eaa18d6-423c-462b-bf1c-ce82dccc5dc5.png" width="354" height="180"&gt;&lt;/p&gt; &lt;p&gt;Remember to do the same for &lt;em&gt;“www.youdomainname.com.”&lt;/em&gt; if you also use www. in your domain name.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Setup your website’s mail (MX record)&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Setup a DNS server to store the configuration for &lt;strong&gt;&lt;em&gt;yourdomain.com&lt;/em&gt;&lt;/strong&gt;&amp;nbsp; (Follow steps 1 and 2 above from your website if you haven’t already).  &lt;li&gt;Create a new MX record that points at your mail servers IP address or hostname.  &lt;li&gt;Setup your mail server to listen to receive mail for &lt;em&gt;yourdomain.com&lt;/em&gt;  &lt;li&gt;Test that all the above is setup correctly using &lt;em&gt;nslookup&lt;/em&gt; as per below.  &lt;li&gt;Try and send and receive email to and from your domain name.  &lt;li&gt;&lt;a href="http://www.diaryofaninja.com/blog/2011/09/27/what-all-good-web-developers-should-know-about-sending-email" target="_blank"&gt;Setup SPF records&lt;/a&gt;, to verify your mail server’s ability to send mail on behalf of your domain name &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Testing your website’s MX record&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In a command prompt/terminal type &lt;em&gt;NSLOOKUP&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Enter “&lt;em&gt;set type=mx&lt;/em&gt;” and hit enter. This set the query type to MX records.&lt;/p&gt; &lt;p&gt;Enter “&lt;em&gt;yourdomainname.com.&lt;/em&gt;” (including the extra period on the end) and hit enter&lt;/p&gt; &lt;p&gt;Check that the returned record value/IP address(es) is that of your mail server.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/b91541e1-ba86-432d-8f1e-aeaa4a95f29b_image_c4366052-ae81-4c70-b278-bc649d7c1c07.png" width="354" height="180"&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;a name="investigate"&gt;&lt;/a&gt; &lt;h2&gt;Investigating Common Problems &lt;/h2&gt; &lt;h3&gt;How do I check what DNS server is &lt;em&gt;authorative&lt;/em&gt; for my domain name?&lt;/h3&gt; &lt;p&gt;You’ve set up your websites DNS, everything is fine; then one day, everyone visiting your site is directed to a site that isn’t yours!&lt;/p&gt; &lt;p&gt;To check which DNS server is &lt;em&gt;authorative&lt;/em&gt; for your domain name, first open a command prompt or terminal.&lt;/p&gt; &lt;p&gt;Type “&lt;em&gt;NSLOOKUP&lt;/em&gt;” and hit enter&lt;/p&gt; &lt;p&gt;Type ”&lt;em&gt;set type=ns&lt;/em&gt;” and hit enter. This sets the query type to NS (NameServer) records.&lt;/p&gt; &lt;p&gt;Type “&lt;em&gt;yourdomainname.com.&lt;/em&gt;” and hit enter (make sure you put the extra dot on the end.)&lt;/p&gt; &lt;p&gt;Confirm that the nameserver’s returned are yours.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/136bf946-d129-4379-a2b2-2071ccf13a20_image_d406c569-3d43-43d2-823f-87456675290a.png" width="354" height="180"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;How do I check what IP address my site is currently pointing at?&lt;/h3&gt; &lt;p&gt;In a command prompt/terminal launch &lt;em&gt;NSLOOKUP&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Enter “&lt;strong&gt;yourdomainname.com.&lt;/strong&gt;” (including the extra period on the end) and hit enter&lt;/p&gt; &lt;p&gt;Check that the returned record value/IP address is that of your web server.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/188e0cf3-2f70-4488-b4ad-313f1728ea29_image_21f67b3b-2c31-4b92-af3d-51807bc57c6e.png" width="354" height="180"&gt;&lt;/p&gt; &lt;p&gt;Remember to do the same for &lt;strong&gt;“www.youdomainname.com.”&lt;/strong&gt; if you also use www. in your domain name.&lt;/p&gt; &lt;h3&gt;What is split DNS?&lt;/h3&gt; &lt;p&gt;Split DNS is when you run a separate DNS forest for a domain name both on your external DNS servers (for everyone else to see) and also internally for staff or local users to see.&lt;/p&gt; &lt;p&gt;This allows you to do things like:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Ensure local users talk to your mail server (or any other internal server) using the internal IP address, and internet users talk to your mail server’s external DMZ IP address.  &lt;li&gt;Block access to certain sites by giving incorrect or different DNS results for these site’s domain names. This if often how many net nanny etc softwares work. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;For some users my sites seems to be served from a different address – how do I check “what the world sees” vs. “what I see”?&lt;/h3&gt; &lt;p&gt;Many things can occur that result in some people seeing different DNS results to others:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Your ISP/company’s DNS server may have an older cached record to the current live record  &lt;li&gt;Your local computer may be caching the DNS record you are requesting  &lt;li&gt;Your local DNS server may be fetching the records for your domain from a different authorative DNS server than the rest of the world. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;How do you investigate these things?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The easiest way to investigate these things is to query an external DNS server that &lt;em&gt;you know is good&lt;/em&gt; for the records you want, to get a better idea of how the rest of the world sees things.&lt;/p&gt; &lt;p&gt;A really good server that is easy to remember are the ones owned by Google. The primary and secondary DNS server for Google’s Public DNS system are “8.8.8.8” and “8.8.4.4” respectively.&lt;/p&gt; &lt;p&gt;You can use whatever DNS servers you think are more likely to see the correct values.&lt;/p&gt; &lt;p&gt;To do this, open a command prompt/console.&lt;/p&gt; &lt;p&gt;Type “&lt;em&gt;NSLOOKUP&lt;/em&gt;” and hit enter&lt;/p&gt; &lt;p&gt;Type “&lt;em&gt;server 8.8.8.8&lt;/em&gt;” and hit enter. This sets the DNS server we will query to the Google Public DNS server’s address.&lt;/p&gt; &lt;p&gt;Type “&lt;em&gt;yourdomainname.com.&lt;/em&gt;” and check the resulting record values.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/a865bebc-c559-41ef-9500-18b9f55d919e_image_e647f2bb-6a7a-459f-adef-f272eab60830.png" width="354" height="180"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lYpy3TSjXKhFVkxEVOsyfbCo9qQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lYpy3TSjXKhFVkxEVOsyfbCo9qQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lYpy3TSjXKhFVkxEVOsyfbCo9qQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lYpy3TSjXKhFVkxEVOsyfbCo9qQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=RQ-N6_usLcM:rp8J0ij4_BY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=RQ-N6_usLcM:rp8J0ij4_BY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=RQ-N6_usLcM:rp8J0ij4_BY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=RQ-N6_usLcM:rp8J0ij4_BY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/uCEJVbJKqpI" height="1" width="1"/&gt;</description><pubDate>3/3/2012 1:06:51 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/03/03/devops-dns-for-developers-ndash-now-therersquos-no-excuse-not-to-know</feedburner:origLink></item><item><title>What ASP.Net MVC Developers Can Learn From GitHub’s Security Woes</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/rdzukFp1uS8/what-aspnet-mvc-developers-can-learn-from-githubrsquos-security-woes</link><description>&lt;p&gt;Over the last week a few stories have moved through the Ruby On Rails and wider development community as one of their shining stars, GitHub was &lt;a href="http://www.theregister.co.uk/2012/03/05/github_hack/"&gt;hacked&lt;/a&gt; to draw attention to some of the weaknesses that can come about from ROR’s convention-based model binding. The interesting thing about the security hole found at GitHub is that it is not necessarily limited to Ruby On Rails, but often comes from using a framework that supports model binding out of the box without understanding the security limitations up front. It also brings a question to the fore: Is it the role of framework developers to force any security configuration to be the default instead of being explicitly applied?&lt;/p&gt;  &lt;p&gt;&lt;img style="margin: 10px 0px 10px 10px; display: inline; float: right" title="image" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/2026c129-54f3-41f6-8593-bc3c517350fe_image_22a8d032-ad09-4549-be81-dcb7b1644f80.png" width="240" height="218" /&gt;A ROR developer &lt;a href="http://homakov.blogspot.com.au/2012/03/how-to.html"&gt;Egor Homakov&lt;/a&gt;, found a configuration vulnerability in the ROR framework’s scaffolding. This vulnerability affected all ROR sites that had been developed using the basic scaffolding that comes out of the box without consideration for security issues, and its implementation of relationship links between data access classes. &lt;/p&gt;  &lt;p&gt;Initially Egor, tried to bring attention to this by posting an Issue to the &lt;a href="https://github.com/rails/rails/issues/5228"&gt;Ruby On Rails Github site&lt;/a&gt;. After not receiving the response he thought the Rails community should have been giving to such a wide affecting security configuration bug, posted a message with a timestamp 1,000 years in the future and then added his private key to the Rails group and uploaded a (completely innocuous) file to the Rails Git repository – all to prove his point.&lt;/p&gt;  &lt;p&gt;What I'll show you below, is the problem that GitHub had, how this can also occur in a hypothetical situation in ASP.Net MVC, and what you can do about it.&lt;/p&gt;  &lt;h2&gt;Let’s Run Over The Problem&lt;/h2&gt;  &lt;p&gt;Ruby On Rails is a pretty slick Ruby framework for building websites &lt;em&gt;fast&lt;/em&gt;, and one of the main ways it does this is by taking a database and scaffolding a site from it, with everything required to get up and running.&lt;/p&gt;  &lt;p&gt;In Ruby On rails, If you have a data model that looks like this (the foreign key would actually not be included in your model object, ROR injects this for you):&lt;/p&gt;  &lt;p&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/90fc761d-6e6b-4c68-8731-2f73ce1a5527_image_0c78c83f-7edc-4626-8855-495a60734701.png" width="341" height="254" /&gt;&lt;/p&gt;  &lt;p&gt;When you scaffold the tables you get code that looks like this (I've removed any code we aren’t going to talk about):&lt;/p&gt;  &lt;pre class="code"&gt;# == Schema Information
# Table name: users
#
#  id                         :integer(11)     not null, primary key
#  email                      :string(255)     
#  username                   :string(255)     
#  password                   :string(255)
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;User &lt;/span&gt;&amp;lt; ActiveRecord::Base
  belongs_to :&lt;span style="color: red"&gt;securityroles

  &lt;/span&gt;validates_presence_of :email, :password
  validates_uniqueness_of :email

  ...
  #class scaffolding code
  ...

end

# == Schema Information
# Table name: securityroles
#
#  id                         :integer(11)     not null, primary key
#  roleName                   :string(255)     not null
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SecurityRole &lt;/span&gt;&amp;lt; ActiveRecord::Base
  has_many :&lt;span style="color: red"&gt;users

  &lt;/span&gt;validates_presence_of :roleName
  ...
  #class scaffolding code
  ...

  def update
    @user = User.find(&lt;span style="color: blue"&gt;params&lt;/span&gt;[:id])
 
    respond_to &lt;span style="color: blue"&gt;do &lt;/span&gt;|format|
      &lt;span style="color: blue"&gt;if &lt;/span&gt;@user.update_attributes(&lt;span style="color: blue"&gt;params&lt;/span&gt;[:user])
        flash[:notice] = &lt;span style="color: #a31515"&gt;'User was successfully updated.'
        &lt;/span&gt;format.html { redirect_to(&lt;span style="color: red"&gt;@user&lt;/span&gt;) }
      &lt;span style="color: blue"&gt;else
        &lt;/span&gt;format.html { &lt;span style="color: red"&gt;render &lt;/span&gt;:&lt;span style="color: red"&gt;action &lt;/span&gt;=&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;edit&amp;quot; &lt;/span&gt;}
      end
    end
  end
end&lt;/pre&gt;

&lt;p&gt;You’ll notice above that the main thing to be concerned about with this scaffolded code is the part where it says this:&lt;/p&gt;

&lt;pre class="code"&gt;def update
  @user = User.find(&lt;span style="color: blue"&gt;params&lt;/span&gt;[:id])
 
  respond_to &lt;span style="color: blue"&gt;do &lt;/span&gt;|format|
    &lt;span style="color: blue"&gt;if &lt;/span&gt;@user.update_attributes(&lt;span style="color: blue"&gt;params&lt;/span&gt;[:user])
      flash[:notice] = &lt;span style="color: #a31515"&gt;'User was successfully updated.'
      &lt;/span&gt;format.html { redirect_to(&lt;span style="color: red"&gt;@user&lt;/span&gt;) }
    &lt;span style="color: blue"&gt;else
      &lt;/span&gt;format.html { &lt;span style="color: red"&gt;render &lt;/span&gt;:&lt;span style="color: red"&gt;action &lt;/span&gt;=&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;edit&amp;quot; &lt;/span&gt;}
    end
  end
end&lt;/pre&gt;

&lt;p&gt;What ROR is doing here is a feature they call “Mass assignment”. &lt;/p&gt;

&lt;p&gt;What the above code is doing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pulling a &lt;em&gt;User&lt;/em&gt; record from the database using the incoming parameter &lt;em&gt;id&lt;/em&gt; to find it. &lt;/li&gt;

  &lt;li&gt;Binding all the other incoming Request parameters to the data model loaded from the database and updating them. &lt;/li&gt;

  &lt;li&gt;Saving the new model back to the database. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Egor’s attack on GitHub, was dead simple in that he simply &lt;em&gt;added a new field to the page&lt;/em&gt; that submitted new SSH keys for a user that had the field name of &lt;em&gt;id,&lt;/em&gt; and he then proceeded to make this field’s value the id for the &lt;em&gt;Ruby On Rails&lt;/em&gt; project owner. This caused the above default scaffolding code to save his GitHub SSH Private key not to his own GitHub account, but to the &lt;em&gt;Ruby On Rails GitHub Account.&lt;/em&gt; Sneaky. Also a very basic oversight by GitHub.&lt;/p&gt;

&lt;p&gt;To be fair to Ruby On Rails, there is a way to stop this kind of attack by marking your class with the property &lt;a href="http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class"&gt;attr_accessible nil&lt;/a&gt; to turn off mass assignment support for a class unless specified so you can white list only the fields you want to bind by hand – the problem with this feature is that it is not &lt;u&gt;the default&lt;/u&gt;. You have have to do this manually – and we all know how easy it to skip or forget about these things in the rush to meet a deadline.&lt;/p&gt;

&lt;p&gt;In ASP.net MVC this ROR functionality would be similar to our model binding. Obviously the code that the ROR scaffolding tool creates is a lot more functional than we get out of the box with ASP.Net MVC, but the CRUD functionality they are creating is very similar across all web platforms. In ASP.Net MVC you have to write your own CRUD code to add, edit and update records and ASP.Net MVC tries to make this simpler by adding Model Binding into the mix. &lt;/p&gt;

&lt;p&gt;In some ways the security concerns this raises are greater because as if you are a junior developer you might not be clear on any potential nasties that can come about if when you write insecure code, or what this even includes.&lt;/p&gt;

&lt;h2&gt;What This Behaviour Look Like In Practice&lt;/h2&gt;

&lt;p&gt;To take a look at what this would entail in ASP.Net MVC let’s think about how the above Ruby on Rails data model application would actually play out in real life using ASP.Net MVC.&lt;/p&gt;

&lt;p&gt;You would most probably have a membership based site where users log in, have different levels of access to things, and can change their settings.&lt;/p&gt;

&lt;p&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/1c47b5aa-aef1-4fd0-86f4-a91acf1abad5_image_e63ac99e-d86b-4def-bd03-83b3eb8cecea.png" width="450" height="196" /&gt;&lt;/p&gt;

&lt;p&gt;If you weren’t switched on and you were new to ASP.Net MVC and web development it would be easy to write a user settings page that looked like this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;(Html.BeginForm()) {
    &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationSummary()
    &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;fieldset&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;legend&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Account Information&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;legend&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;

            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-label&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.LabelFor(m =&amp;gt; m.Name)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-field&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.TextBoxFor(m =&amp;gt; m.Name)
                &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationMessageFor(m =&amp;gt; m.Name)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            
             &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-label&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.LabelFor(m =&amp;gt; m.Email)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-field&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.TextBoxFor(m =&amp;gt; m.Email)
                &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationMessageFor(m =&amp;gt; m.Email)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;input &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;submit&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Change Account Details&amp;quot; /&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;fieldset&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;}&lt;/pre&gt;

&lt;p&gt;And your settings controller &lt;em&gt;could&lt;/em&gt; look like:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;Authorize&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails()
{
    &lt;span style="color: blue"&gt;var &lt;/span&gt;dbUser = DAL.&lt;span style="color: #2b91af"&gt;UserRepository&lt;/span&gt;.Load(x =&amp;gt; x.Username = User.Identity.Name);
    &lt;span style="color: blue"&gt;var &lt;/span&gt;model = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;UserModel&lt;/span&gt;(dbUser);
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(model);
}
[&lt;span style="color: #2b91af"&gt;Authorize&lt;/span&gt;]
[&lt;span style="color: #2b91af"&gt;HttpPost&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails(&lt;span style="color: #2b91af"&gt;UserModel &lt;/span&gt;model)
{
    DAL.&lt;span style="color: #2b91af"&gt;User &lt;/span&gt;dbUser = DAL.&lt;span style="color: #2b91af"&gt;UserRepository&lt;/span&gt;.Load(x =&amp;gt; x.Username = User.Identity.Name);
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(TryUpdateModel(dbUser))
    {
        DAL.&lt;span style="color: #2b91af"&gt;User&lt;/span&gt;.Save(dbUser);
        &lt;span style="color: blue"&gt;return &lt;/span&gt;RedirectToAction(&lt;span style="color: #a31515"&gt;&amp;quot;ChangeDetailsSuccess&amp;quot;&lt;/span&gt;);
    }
       
    ModelState.AddModelError(&lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Something went wrong&amp;quot;&lt;/span&gt;);
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(model);
}&lt;/pre&gt;


&lt;h2&gt;What’s Wrong With This Code?&lt;/h2&gt;

&lt;p&gt;If you’re stumped looking at the above code to find any issues, it’s time to start thinking about one of the golden rules of web development security; &lt;u&gt;White Listing&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;The exact same problem that affects the Ruby On Rails community in the GitHub hack with their mass assignment “bug” (if we even call it that), is that the above ASP.Net MVC code &lt;em&gt;blindly&lt;/em&gt; binds &lt;em&gt;any&lt;/em&gt; incoming request parameters to our database model.&lt;/p&gt;

&lt;p&gt;&lt;img style="display: inline" title="image" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/1fd76f3e-e6ac-42f6-835e-d23387fd5353_image_3.png" width="633" height="156" /&gt;&lt;/p&gt;

&lt;p&gt;This is exactly the same problem that allowed Egor to be able to hack GitHub:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We &lt;u&gt;don’t&lt;/u&gt; specify what incoming parameters we &lt;em&gt;actually&lt;/em&gt; care about.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This can lead to all manner of implicit security or data quality issues on your sites, because users can potentially hijack your own code for other purposes – it’s kind of like the modern equivalent of &lt;a href="http://www.troyhunt.com/2010/05/owasp-top-10-for-net-developers-part-1.html"&gt;SQL Injection&lt;/a&gt;, but through binding code!&lt;/p&gt;

&lt;h2&gt;How could we hack the above piece of MVC code?&lt;/h2&gt;

&lt;p&gt;The problem that could affect any ASP.Net MVC site that isn’t verifying all incoming user submitted data, usually comes about not when the site is used as intended – but when new parts are added to the request.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The site gives us data.&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;We send the updated data back.&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;&lt;strong&gt;But we also added something sneaky along for the ride.&lt;/strong&gt;&lt;/em&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lets change our Account Settings page, and add a new field.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;(Html.BeginForm()) {
    &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationSummary()
    &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;fieldset&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;legend&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Account Information&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;legend&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;

            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-label&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.LabelFor(m =&amp;gt; m.Name)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-field&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.TextBoxFor(m =&amp;gt; m.Name)
                &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationMessageFor(m =&amp;gt; m.Name)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            
             &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-label&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.LabelFor(m =&amp;gt; m.Email)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;div &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;editor-field&amp;quot;&amp;gt;
                &lt;/span&gt;&lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.TextBoxFor(m =&amp;gt; m.Email)
                &lt;span style="background: yellow"&gt;@&lt;/span&gt;Html.ValidationMessageFor(m =&amp;gt; m.Email)
            &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;strong&gt;            &lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: #006400"&gt;&amp;lt;!--                 
                #HACK ATTACK#                
                THIS FIELD WILL SET OUR ROLE ID TO &amp;quot;1&amp;quot; 
            --&amp;gt;
            &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;input &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;text&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;SecurityRoles_Id&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;value&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: blue"&gt;&lt;strong&gt;=&amp;quot;1&amp;quot;/&amp;gt;
            &lt;/strong&gt;&lt;/span&gt;&lt;span style="color: #006400"&gt;&lt;strong&gt;&amp;lt;!-- --&amp;gt;&lt;/strong&gt;
            &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: maroon"&gt;input &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;submit&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Change Account Details&amp;quot; /&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;fieldset&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;}&lt;/pre&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The site gives us our page.&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;We add a new field, named &lt;em&gt;SecurityRoles_Id&lt;/em&gt; to the page using Firebug etc.&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;When we submit the page back the site would set our security role foreign key to 1.&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see from my above view code that if I added this field in Firebug or developer tools and submitted it back to the site, I would have changed my role in the site’s database to whatever role was stored in the database’s roles tables with the Id of 1. &lt;/p&gt;

&lt;p&gt;Think back to when you first set up your database – What was the first user (record number 1) you added to your database, an Admin? What was the first role (record number 1) you added to your Security&amp;#160; Roles table, Admin?&lt;/p&gt;

&lt;p&gt;This problem is ever simpler if you have a user table that simply has a Boolean field called something like &lt;em&gt;“IsAdmin”&lt;/em&gt; to define the users permissions as an attacker wouldn’t have to guess what the id of a nice juicy role is set to.&lt;/p&gt;

&lt;p&gt;I understand that looking at the above attack you have to know that my database field was called &lt;em&gt;securityroles_id&lt;/em&gt; but if you ask anyone working in web security they’ll tell you have unless a site has &lt;strong&gt;also&lt;/strong&gt; locked down all its error messaging or tracing this can be sometimes easy enough to find out using other attacks first to probe your data model and review the errors thrown.&lt;/p&gt;

&lt;h2&gt;Batten Down The Hatches&lt;/h2&gt;

&lt;h3&gt;Whitelist your submitted data&lt;/h3&gt;

&lt;p&gt;When visitors to your site submit data back to you, always white list the fields you are saving to the database. This means manually bind or copy &lt;u&gt;only &lt;/u&gt;the fields you want to save from the request – don’t just bind the whole model to a database record.&lt;/p&gt;

&lt;p&gt;Use model binding carefully with sensitive data to avoid any accidental oversights while developing your application.&lt;/p&gt;

&lt;p&gt;ASP.Net MVC supports protection against this in a similar way to Ruby On Rails’ &lt;a href="http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class"&gt;attr_accessible nil&lt;/a&gt; by enabling your controller action to use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute.aspx"&gt;Bind Attribute&lt;/a&gt;&amp;#160;&lt;strong&gt;[Bind(Include=*explicit properties here*)]&lt;/strong&gt; when defining your incoming model binding. Just like ROR however, this is not turned on by default…&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails([&lt;span style="color: #2b91af"&gt;Bind&lt;/span&gt;(Include = &lt;span style="color: #a31515"&gt;&amp;quot;Name,Email&amp;quot;&lt;/span&gt;)] &lt;span style="color: #2b91af"&gt;User &lt;/span&gt;model)
{
    ...
}&lt;/pre&gt;

&lt;p&gt;If your model class has many fields you can work backwards, and &lt;em&gt;exclude&lt;/em&gt; properties from binding instead;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails([&lt;span style="color: #2b91af"&gt;Bind&lt;/span&gt;(Exclude = &lt;span style="color: #a31515"&gt;&amp;quot;SecurityRoles_Id&amp;quot;&lt;/span&gt;)] &lt;span style="color: #2b91af"&gt;User &lt;/span&gt;model)
{
    ...
}&lt;/pre&gt;

&lt;p&gt;You can also use the additional overloads of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel.aspx"&gt;TryUpdateModel&lt;/a&gt; method to define what objects to bind, &lt;em&gt;or not bind&lt;/em&gt; from the FormCollection if you are using this method of model binding/validation.&lt;/p&gt;

&lt;p&gt;Include;&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;Authorize&lt;/span&gt;]
[&lt;span style="color: #2b91af"&gt;HttpPost&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails(&lt;span style="color: #2b91af"&gt;UserModel &lt;/span&gt;model)
{
    DAL.&lt;span style="color: #2b91af"&gt;User &lt;/span&gt;dbUser = DAL.&lt;span style="color: #2b91af"&gt;UserRepository&lt;/span&gt;.Load(x =&amp;gt; x.Username = User.Identity.Name);
    &lt;span style="color: blue"&gt;string&lt;/span&gt;[] includeInModel = &lt;span style="color: blue"&gt;new&lt;/span&gt;[] { &lt;span style="color: #a31515"&gt;&amp;quot;EmailAddress&amp;quot; &lt;/span&gt;}; 
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(TryUpdateModel(dbUser, includeInModel))
    {
        DAL.&lt;span style="color: #2b91af"&gt;User&lt;/span&gt;.Save(dbUser);
        &lt;span style="color: blue"&gt;return &lt;/span&gt;RedirectToAction(&lt;span style="color: #a31515"&gt;&amp;quot;ChangeDetailsSuccess&amp;quot;&lt;/span&gt;);
    }
    ModelState.AddModelError(&lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Something went wrong&amp;quot;&lt;/span&gt;);
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(model);
}&lt;/pre&gt;


&lt;p&gt;Exclude;&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;Authorize&lt;/span&gt;]
[&lt;span style="color: #2b91af"&gt;HttpPost&lt;/span&gt;]
&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails(&lt;span style="color: #2b91af"&gt;UserModel &lt;/span&gt;model)
{
    DAL.&lt;span style="color: #2b91af"&gt;User &lt;/span&gt;dbUser = DAL.&lt;span style="color: #2b91af"&gt;UserRepository&lt;/span&gt;.Load(x =&amp;gt; x.Username = User.Identity.Name);
    &lt;span style="color: blue"&gt;string&lt;/span&gt;[] excludeInModel = &lt;span style="color: blue"&gt;new&lt;/span&gt;[] { &lt;span style="color: #a31515"&gt;&amp;quot;SecurityRoles_Id&amp;quot; &lt;/span&gt;}; 
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(TryUpdateModel(dbUser, &lt;span style="color: blue"&gt;string&lt;/span&gt;.Empty, &lt;span style="color: blue"&gt;null&lt;/span&gt;, excludeInModel))
    {
        DAL.&lt;span style="color: #2b91af"&gt;User&lt;/span&gt;.Save(dbUser);
        &lt;span style="color: blue"&gt;return &lt;/span&gt;RedirectToAction(&lt;span style="color: #a31515"&gt;&amp;quot;ChangeDetailsSuccess&amp;quot;&lt;/span&gt;);
    }
    ModelState.AddModelError(&lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Something went wrong&amp;quot;&lt;/span&gt;);
    &lt;span style="color: blue"&gt;return &lt;/span&gt;View(model);
}&lt;/pre&gt;


&lt;p&gt;Also, if you have complex types in your view model (Entity Framework objects etc.) you should abstract your data layer away into a separate project. Other than the fact that you should never have complex types of dependencies in your models, doing this ensures that even if you do step on a land mine by accident, you aren’t talking directly to the database and can have a little more control. If you are only new to this additional separation and are cringing at the thought of all the additional code you’ll have to write, take a look at something like &lt;a href="http://automapper.codeplex.com/"&gt;AutoMapper&lt;/a&gt; to do this for you (ASP.Net MVC 3 has the TryUpdateModel method that I used in my first example that does this for you as well – albeit with less control).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ActionResult &lt;/span&gt;ChangeAccountDetails(&lt;span style="color: #2b91af"&gt;UserModel &lt;/span&gt;model)
{
    &lt;span style="color: green"&gt;//create a new User object
    &lt;/span&gt;DAL.&lt;span style="color: #2b91af"&gt;User &lt;/span&gt;u = &lt;span style="color: blue"&gt;new &lt;/span&gt;DAL.&lt;span style="color: #2b91af"&gt;User&lt;/span&gt;();
    &lt;span style="color: green"&gt;// map the incoming model to the user object
    &lt;/span&gt;AutoMapper.&lt;span style="color: #2b91af"&gt;Mapper&lt;/span&gt;.Map(u, model);

    &lt;span style="color: green"&gt;//
    // Some code that attaches our object 
    // to the current record in the DB that 
    // matches User.Identity.Name
    //
    &lt;/span&gt;DAL.&lt;span style="color: #2b91af"&gt;User&lt;/span&gt;.Save(u);
    &lt;span style="color: blue"&gt;return &lt;/span&gt;RedirectToAction(&lt;span style="color: #a31515"&gt;&amp;quot;ChangeDetailsSuccess&amp;quot;&lt;/span&gt;);
}&lt;/pre&gt;

&lt;h3&gt;Turn Off Any Exception Signalling&lt;/h3&gt;

&lt;p&gt;Ensure that all tracing and exceptions are turned off on your site to avoid probing. This means turning &lt;a href="http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx"&gt;friendly error messages on&lt;/a&gt; to avoid any exceptions being handed out to attackers wanting to test the waters, &lt;a href="http://msdn.microsoft.com/en-us/library/0x5wc973.aspx"&gt;ensuring tracing is turned off&lt;/a&gt;, and take a read of &lt;a href="http://www.troyhunt.com/2010/05/owasp-top-10-for-net-developers-part-1.html"&gt;Troy Hunt series on OWASP security vulnerabilities&lt;/a&gt; that can often occur during application development without you being aware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Machine.config&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;turn on retail mode &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;deployment &lt;/span&gt;&lt;span style="color: red"&gt;retail&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Web.config&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;    
    &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;turn debug mode off &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;compilation &lt;/span&gt;&lt;span style="color: red"&gt;debug&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;    
    &amp;lt;!— &lt;/span&gt;&lt;span style="color: green"&gt;turn On custom errors &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;customErrors &lt;/span&gt;&lt;span style="color: red"&gt;mode&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;RemoteOnly&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;!-- &lt;/span&gt;&lt;span style="color: green"&gt;turn tracing off (this is set to false by default) &lt;/span&gt;&lt;span style="color: blue"&gt;--&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;trace &lt;/span&gt;&lt;span style="color: red"&gt;enabled&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;system.web&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;  
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;While more senior web developers working on the ASP.Net MVC stack may think the issues I've raised are too hypothetical and easy to overcome, I can assure you from much experience working with developers of all sorts of skill levels over the years that these types of inherent “you’d never do that, it’s silly” problems are usually the ones I’ve see most. &lt;/p&gt;

&lt;p&gt;GitHub’s problems were more related to the way ROR does it’s scaffolding, but it just goes to show that development techniques that save time by writing the code for you (such as ASP.Net MVC’s Model Binding) can often lead to a disconnect between the developer and his application’s code – if a large company like GitHub can miss these problems, its proof that these problems are more of a commonplace occurrence than we’d all like to think.&lt;/p&gt;

&lt;p&gt;When saving any user generated data, be sure to only save what you intend to for a given action, and ensure they have permission to do so before putting saving it to your database.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/58wDsXiIayqtd7Z3BYQ3CQpM7hg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/58wDsXiIayqtd7Z3BYQ3CQpM7hg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/58wDsXiIayqtd7Z3BYQ3CQpM7hg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/58wDsXiIayqtd7Z3BYQ3CQpM7hg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eST0_lWuJHw:cSD2asY1dC0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eST0_lWuJHw:cSD2asY1dC0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=eST0_lWuJHw:cSD2asY1dC0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=eST0_lWuJHw:cSD2asY1dC0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/rdzukFp1uS8" height="1" width="1"/&gt;</description><pubDate>3/11/2012 7:01:00 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/03/11/what-aspnet-mvc-developers-can-learn-from-githubrsquos-security-woes</feedburner:origLink></item><item><title>The Line Between Insanity and Genius. Where Do You Draw Yours?</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/GqZX9EswXEg/the-line-between-insanity-and-genius-where-do-you-draw-yours</link><description>&lt;p&gt;As Software Developers, our passion can sometimes be all encompassing. You can find a new language or framework and something inside you lights a spark and the obsession begins – it’s part of what makes a great scientist, developer, engineer or doctor. It can also be a part of what drives people insane. Recently I've wondered where the line is, when its time to back off, or even if you should.&lt;/p&gt;  &lt;p&gt;Lately I've had a few moments of introspection which some may view as disturbing, and others may celebrate: the realisation that a large part of my career’s success, and my personality could easily be misconstrued as mental illness if looked at under the wrong light.&lt;/p&gt;  &lt;h3&gt;&lt;a href="http://www.flickr.com/photos/pamilne/2081446863/"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/89547f70-ac46-4f13-afaa-1d92690ceb40_image_3.png" width="224" height="244" /&gt;&lt;/a&gt;Obsession – It can be never ending&lt;/h3&gt;  &lt;p&gt;I can find parts of technology or programming that can consume me. It'll be all I think about night and day for weeks. &lt;/p&gt;  &lt;p&gt;Remember that time you asked me a question and I might not have responded straight away? I was probably thinking about that new framework, design pattern, process or technology I was hooked on. Thinking about my social life it has probably limited my interaction with the world multiple times over the course of my life. &lt;/p&gt;  &lt;p&gt;When it comes to work, it can be a dangerous thing for totally other reasons. When do you stop pushing for perfection to save wasting money, resources or staff members. How do you explain this to non-technical members at your workplace.&lt;/p&gt;  &lt;p&gt;Not too long ago in &lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/a&gt; and &lt;a href="http://blog.wekeroad.com/"&gt;Rob Conery&lt;/a&gt;’s “This Developers Life” episode on “&lt;a href="http://thisdeveloperslife.com/post/1-1-4-obsession"&gt;Obsession&lt;/a&gt;”, they talked to Rob Sullivan and Rory Blyth about what drives them as developers, and how they became obsessed with technology – and how they sometimes find it hard to unplug; hard to even get &lt;em&gt;themselves&lt;/em&gt; to step away from a problem. &lt;/p&gt;  &lt;p&gt;For me I find this very inner torture happening all the time.&lt;/p&gt;  &lt;p&gt;The most poignant quote I took away from that podcast (I listened to it again recently), was Rob Sullivan’s quote:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“…&lt;/p&gt;    &lt;p&gt;As I’ve looked back and thought about everything I've done over the last couple of years, I had a conversation with myself… So I asked myself a question in my head, ‘What do I want to do for fun’, and then i got into this very Socratic Dialectic interaction with myself about ‘Ok, fine so what is fun? Define fun.’ and I could not figure out what fun was. &lt;/p&gt;    &lt;p&gt;And I think that’s what happens in the Tech industry. When you are actually into what you are doing, you are having fun, but you are also working; and you &lt;em&gt;never&lt;/em&gt;, &lt;em&gt;ever&lt;/em&gt; stop. You lose perspective.&lt;/p&gt;    &lt;p&gt;…”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is exactly how I feel sometimes.&lt;/p&gt;  &lt;p&gt;I feel that sometimes I want to stop my brain from churning &lt;em&gt;over and over&lt;/em&gt; on a coding problem I’m trying to solve, a topic of conversation I’ve had with someone, or an opinion I just read on a blog. Sometimes I want to switch that part of my brain off so I can relax.&lt;/p&gt;  &lt;p&gt;And it doesn’t end with Tech for me – I have this “obsession” often with everything that I do. I have to figure out or learn about everything I interact with – and Google has made it really easy for people like me to get their next fix.&lt;/p&gt;  &lt;p&gt;“How does the body metabolise different foods?”&lt;/p&gt;  &lt;p&gt;“What frequency do bats use to see in the dark?”&lt;/p&gt;  &lt;p&gt;“&lt;a href="http://en.wikipedia.org/wiki/Red_hair#Pain_tolerance_and_injury"&gt;Do red hair people really need more painkillers than others?&lt;/a&gt;”&lt;/p&gt;  &lt;p&gt;It &lt;em&gt;never ends&lt;/em&gt;. I often cannot stop this type of thinking and have had to create walls and rules to stop it and live a normal life – I don’t take a smart phone out to social occasions anymore.&lt;/p&gt;  &lt;p&gt;This type of obsessive questioning and reasoning inside my head gets me to thinking – “Is there something wrong with me?, Am I starting to go all ‘Beautiful Mind’ on myself?”&lt;/p&gt;  &lt;p&gt;From the small conversations I’ve had with other people in the Tech world, I am not alone here. A large section of us have stopped and questioned ourselves or our drivers.&lt;/p&gt;  &lt;h3&gt;Where is the line?&lt;/h3&gt;  &lt;p&gt;The hard part I find is that I come from a family that has dealt with mental illness. That &lt;em&gt;thing&lt;/em&gt; that no one ever talks about, I dealt with through my mother, who was Schizophrenic and therefore I would think to myself that I think about it more than most. My mother was passionate and intelligent beyond measure – and music was her passion. It was everywhere – it drove mood, it was mathematical, and it was always to be in search of.&lt;/p&gt;  &lt;p&gt;How am I and most really passionate people in the Tech industry any different in some ways?&lt;/p&gt;  &lt;p&gt;When you stay up late into the night trying to finish a game, or complete the next feature in your project; or &lt;em&gt;totally rewrite &lt;/em&gt;that part of a project – Do you actually have control to stop? Do you deep down actually want to stop? And at what point is this lack of control a bad thing?&lt;/p&gt;  &lt;p&gt;What about when you finally have time off work, and all you want to do is start a new Open Source project, or play with a new language (you’re meant to be on &lt;em&gt;holidays&lt;/em&gt; remember?)&lt;/p&gt;  &lt;h3&gt;Others in our industry&lt;/h3&gt;  &lt;p&gt;Since Steve Jobs died recently, there where many stories and rumours of how he dealt with work life at Apple and his obsession for perfection. If Steve had another obsession that wasn’t creating number one selling consumer devices, would people have the same feelings for his life’s deliverables?&lt;/p&gt;  &lt;p&gt;There has often been questions of &lt;a href="http://gawker.com/5885196/the-tech-industrys-asperger-problem-affliction-or-insult"&gt;Mark Zuckerberg’s potential case of Asperger’s syndrome&lt;/a&gt;. This very same article talks about tech and it’s connection to these types of obsessive and rigid character traits - however science likes to define them. There has likewise been suggestion that many other people in tech, Bill Gates included, might show symptoms of Asperger’s.&lt;/p&gt;  &lt;p&gt;Regardless of definition, I know I'm not alone here in thinking that sometimes my obsessive or focused behaviour might not be normal.&lt;/p&gt;  &lt;p&gt;Where do you define what is healthy when having a passion for something – Is this something society defines to you, or do you set the goal posts? And if you, how do you stop yourself from moving the goal posts through self-justification?&lt;/p&gt;  &lt;p&gt;If you are passionate to the point of changing parts of your life to suit your passion – where is the line between passion and craziness, insanity and genius? And given my experience; If you ever think you cross the line – how do you have the strength to take heed?&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Picture of the Sistine Chapel by &lt;a href="http://www.flickr.com/photos/pamilne/"&gt;féileacán&lt;/a&gt; licensed under Creative Commons.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CjSDNNCbu6xan-cixcaOlTzbyr4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CjSDNNCbu6xan-cixcaOlTzbyr4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CjSDNNCbu6xan-cixcaOlTzbyr4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CjSDNNCbu6xan-cixcaOlTzbyr4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=pDDsRKdrrn4:FCwF8shRq7g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=pDDsRKdrrn4:FCwF8shRq7g:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=pDDsRKdrrn4:FCwF8shRq7g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=pDDsRKdrrn4:FCwF8shRq7g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/GqZX9EswXEg" height="1" width="1"/&gt;</description><pubDate>3/25/2012 5:35:00 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/03/25/the-line-between-insanity-and-genius-where-do-you-draw-yours</feedburner:origLink></item><item><title>I’m a Junior Developer – You probably are too</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/0dSYE0dm2tU/irsquom-a-junior-developer-ndash-you-probably-are-too</link><description>&lt;p&gt;Part of my job is hiring people to build websites for advertising clients. Most of the things that we build don’t compete with brain surgery for complexity, but as anyone knows when working in software, having skilled people working on simple problems often leads to scalable, well built solutions – I hire accordingly. The problem is how do you define "skilled" and does it even have meaning in software out of the context of a company’s needs?&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.thebeardly.com/" target="_blank"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 15px 0px 15px 15px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/c64763fd-418e-423c-972a-3865a8dd90bc_image_c74e8a9e-af7f-492a-b566-284c27edf6b5.png" width="244" height="196"&gt;&lt;/a&gt;I have been quite lucky that early in my career I realised that no matter how skilled I got at my craft, there would always be someone on a whole other level. Crossing developers with egos aside, attending conferences, user groups and development events is one of the easiest ways to reset your expectations surrounding skill level, and find this out early.&lt;/p&gt; &lt;h3&gt;I am a Junior Programmer&lt;/h3&gt; &lt;p&gt;I have been developing software since I was 10. Commercially since I was 14 and 9 months (this is the legal age in Australia to work). I have had a go at creating many different types of software in many different programming languages, more recently on the Microsoft stack.&lt;/p&gt; &lt;p&gt;I’ve lead teams, travelled for work, had high risk, low risk, sexy, boring, you name it programming jobs over the years.&lt;/p&gt; &lt;p&gt;All this has made one thing very clear to me:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;I know nothing.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Our industry is so vast, and different technologies and methodologies are so numerous that this single piece of information should go with you everywhere you travel.&lt;/p&gt; &lt;h3&gt;How about you?&lt;/h3&gt; &lt;p&gt;When applying this to hiring though, things are never as clear. Nowhere is this more evident than working in a Sydney advertising agency, and being tasked with hiring web developers.&lt;/p&gt; &lt;p&gt;You see in the land of web development in Sydney, the age of the Brogrammer/Coder is upon us.&lt;/p&gt; &lt;p&gt;Recently I have been tasked with hiring a new senior technical member of staff. I literally did 30 or more phone interviews, many-many in person interviews and the experience left me feeling quite dis-enchanted with the Sydney .Net web world. The amount of 10+ year experience huge salary swinging web developers I saw who couldn't:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Describe how POST data was submitted to a server by a browser.  &lt;li&gt;Explain a number of HTTP status codes (except maybe 404 and 500).  &lt;li&gt;Explain SOLID or name a design pattern.  &lt;li&gt;Explain ways to improve a pages load speed or user experience.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You may think I am being being aggressive in suggesting this, but if you can’t answer the questions above there are a lot of people who wouldn’t think of &lt;em&gt;you as a Senior Web Developer&lt;/em&gt; (maybe we can rule SOLID out… but you understand my point). However what do you call yourself if you have been building websites for 10 years in ASP.Net (or PHP, or Perl, or anything…) and you need a title?&lt;/p&gt; &lt;p&gt;This got me thinking though: how do you define seniority or skill in Software Engineering terms. Especially when hiring.&lt;/p&gt; &lt;p&gt;So many people can have simple roles for long periods of time, where they aren’t necessarily exposed to new principles or changes in their industry – do these people deserve high 6 figure salaries and “Senior” or “Architect” in their job titles?&lt;/p&gt; &lt;p&gt;This is where I think it all comes down to a single word:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Context&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;If you have been building applications, websites, or *&lt;strong&gt;whatever&lt;/strong&gt;* for many many years, you would hope you would have become considerably good at it. This doesn’t make you a senior developer, and this I think often gets lost on most of our ilk. It does make you good at what you have been doing.&lt;/p&gt; &lt;p&gt;But &lt;em&gt;my view&lt;/em&gt; on people compared to &lt;em&gt;your view &lt;/em&gt;on a candidate and their skills might be totally different – because I am totally blinded by the context for which I need from my new team member. My definition of senior will be totally different from that of someone hiring at a place that builds landing systems for spacecraft; or someone working on small business accounting packages.&lt;/p&gt; &lt;p&gt;In my hiring case, I was looking for someone who had a fair bit of experience building websites in ASP.Net and c# among other things. Not someone to build the next Google. However our industry only thinks of people in terms. “Junior ASP.Net developer”, “Senior Ruby programmer”,”Mid level PHP developer”. I don’t think this describes people’s experience or knowledge levels well enough.&lt;/p&gt; &lt;p&gt;Usually this equates to someone who is new, has been around for a while, or is an “old salt” at whatever they were doing – maybe building “Hello World” websites over and over… Who knows?&lt;/p&gt; &lt;p&gt;Maybe it’s time to rewrite how we describe people in our industry. Something similar to &lt;a href="http://www.hanselman.com/blog/FizzBinTheTechnicalSupportSecretHandshake.aspx" target="_blank"&gt;Scott Hanselman’s use of “FizzBin” in technical support calls&lt;/a&gt; might just do…&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RdJfDk5ycTFgwDh4P1zPWJ9IIZc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RdJfDk5ycTFgwDh4P1zPWJ9IIZc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RdJfDk5ycTFgwDh4P1zPWJ9IIZc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RdJfDk5ycTFgwDh4P1zPWJ9IIZc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=tf-ey5rPAZM:hR_5F75izeE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=tf-ey5rPAZM:hR_5F75izeE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=tf-ey5rPAZM:hR_5F75izeE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=tf-ey5rPAZM:hR_5F75izeE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/0dSYE0dm2tU" height="1" width="1"/&gt;</description><pubDate>3/27/2012 6:37:58 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/03/27/irsquom-a-junior-developer-ndash-you-probably-are-too</feedburner:origLink></item><item><title>Things I Missed So You Won’t Have To – WP7 SDK</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/2aNTEc8j9ug/things-i-missed-so-you-wonrsquot-have-to-ndash-wp7-sdk</link><description>&lt;p&gt;During my development journey with Windows Phone 7 , there have been a number of things that I overlooked when writing your first app – things I wished I’d kept front of mind. None of these items are necessarily difficult or complicated things to cover off, so I thought I'd mention them here to save you the trouble, and at the same time show you ways to overcome each of them.&lt;/p&gt;  &lt;h3&gt;&lt;img style="display: inline; float: right" title="image" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/85d1ba4d-5aac-4709-b654-3a5360016c82_image_f05e0100-e00f-4b73-af33-8820a8158246.png" width="270" height="235" /&gt;Globalisation&lt;/h3&gt;  &lt;p&gt;Windows Phone 7 devices have been released to a total &lt;a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/03/15/app-hub-accepting-submissions-for-new-markets-soon.aspx"&gt;63 different markets&lt;/a&gt; at the time of this post’s writing, and while we might not sometimes talk about it too much the majority of the world doesn’t speak English. &lt;/p&gt;  &lt;p&gt;Even more relevant when writing apps that process third party data, lots of countries also don’t use the same date or decimal system as the US or British do – and when parsing dates or numbers in a local region this can easily break your code.&lt;/p&gt;  &lt;p&gt;If you are in France or a large percentage of Europe for example, instead of One Hundred Thousand being written as “100,000.00” as in the US it is instead written as “100 000,00”.&lt;/p&gt;  &lt;p&gt;The way to get around this depends on whether you are &lt;em&gt;receiving&lt;/em&gt; data in a foreign region, or &lt;em&gt;sending&lt;/em&gt; data in a foreign region.&lt;/p&gt;  &lt;p&gt;Below is an example piece of code to represent this problem (This is not how you should your app because it is best practice&amp;#160; to keep the culture local and instead change how you parse).&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;// Switch the current culture to French to simulate a French User
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Thread&lt;/span&gt;.CurrentThread.CurrentCulture = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;fr-FR&amp;quot;&lt;/span&gt;);
&lt;span style="color: #2b91af"&gt;Double &lt;/span&gt;Number = 123.00;

&lt;span style="color: green"&gt;// This will be &amp;quot;123,00&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;string &lt;/span&gt;Output = Number.ToString();

&lt;span style="color: green"&gt;// This will be &amp;quot;123.00&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;string &lt;/span&gt;InvariantOutput = Number.ToString(&lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.InvariantCulture);&lt;/pre&gt;

&lt;p&gt;This means that if you are parsing Strings that are from the US to &lt;a href="http://msdn.microsoft.com/en-us/library/system.int32.aspx"&gt;Ints&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/library/system.double(v=vs.71).aspx"&gt;Doubles&lt;/a&gt; (such as those fetched from remote American APIs such as Twitter or Google) and your users are in France, your app will throw an exception as the number format won’t be properly recognised – you need to either specify the culture of the incoming string or specify the culture as &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.invariantculture.aspx"&gt;Invariant Culture&lt;/a&gt; (defaults to United States).&lt;/p&gt;

&lt;p&gt;Take the following example run on a US based device. Here we take a set the culture to French (to simulate a French user) and then successfully parse the US/British number string.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Double &lt;/span&gt;Number = 123.00;

&lt;span style="color: green"&gt;// This will be &amp;quot;123.00&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;string &lt;/span&gt;Output = Number.ToString();

&lt;span style="color: green"&gt;// Change the current culture to simulate a French User
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Thread&lt;/span&gt;.CurrentThread.CurrentCulture = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;fr-FR&amp;quot;&lt;/span&gt;);

&lt;span style="color: green"&gt;// This will throw an exception
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Double &lt;/span&gt;FrenchParsedNumber = &lt;span style="color: #2b91af"&gt;Double&lt;/span&gt;.Parse(Output);

&lt;span style="color: green"&gt;// This will not throw an exception
&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Double &lt;/span&gt;FrenchParsedNumberInvariant = 
    &lt;span style="color: #2b91af"&gt;Double&lt;/span&gt;.Parse(Output, &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;.InvariantCulture);&lt;/pre&gt;

&lt;p&gt;All of the above examples also &lt;u&gt;definitely&lt;/u&gt; apply to &lt;em&gt;Parsing of Dates. &lt;/em&gt;There is a good write up on MSDN showing how to do this with &lt;a href="http://msdn.microsoft.com/en-us/library/kc8s65zs(v=vs.95).aspx" target="_blank"&gt;DateTime format providers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, You can test your application under different conditions by changing your &lt;a href="http://msdn.microsoft.com/en-us/library/hh487168(v=vs.92).aspx"&gt;emulator’s regional culture&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Localisation&lt;/h3&gt;

&lt;p&gt;While this is not really a problem with your app &lt;em&gt;per se&lt;/em&gt;, while we are on the topic of foreign users it’s worth mentioning&amp;#160; that because very soon only a tiny percentage of the market will be English speaking countries, separating your text content into international resource files will make selling in these markets a lot more lucrative – and anyone who’s done this before will tell you it’s a lot easier if you do this from the start, even if the only language resource you have is English to start with.&lt;/p&gt;

&lt;p&gt;Steps to add local language support to your Windows Phone 7 app pages (Based loosely on this &lt;a href="http://msdn.microsoft.com/en-us/library/ff637520(v=vs.92).aspx" target="_blank"&gt;MSDN article&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Create a new Resource File in your app called &lt;strong&gt;Resources.resx&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/bc7fe87e-237a-4ef1-8fd0-435f2401dc91_image_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/50ac7b84-547f-42d3-86c2-92572b86a653_image_thumb.png" width="454" height="315" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a new file for each additional language you want to support (i.e. named&lt;strong&gt; Resources-FR.resx &lt;/strong&gt;for French, &lt;strong&gt;Resources-ES.resx&lt;/strong&gt; for Spanish).&lt;/p&gt;

&lt;p&gt;The MSDN article linked above shows you how to create the &lt;strong&gt;LocalizedStrings&lt;/strong&gt; class, however they don’t go on to show you how to use it for DataBinding, so lets solve that.&lt;/p&gt;

&lt;p&gt;WPF/ASP.net and Silverlight handle data binding differently than Winforms. Silverlight uses the term Resource to refer to files that use the the Build Action of &amp;quot;Content”, as these files get wrapped up into the .XAP file similar to files with the Build Action of &amp;quot;Resource” get embedded into the .Dll assembly. &lt;/p&gt;

&lt;p&gt;I found that instead of using the &lt;strong&gt;Text=&amp;quot;{Binding Path=resourceFile.resourceName, Source={StaticResource Localizedresources }}&amp;quot;&lt;/strong&gt; XAML syntax it was easier to follow the steps below:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open your primary XAML page (usually MainPage.xaml) in the Visual Studio &lt;/li&gt;

  &lt;li&gt;Open the properties for the PhoneApplicationPage and set the DataContext to be Application.Resources –&amp;gt; LocalizedStrings. NOTE: if you already are using a DataContext object, then you should integrate the LocalizedStrings class into that object so that it has localization support. 
    &lt;br /&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/dfe3ac80-1fc0-44ed-a53f-50951e2e02ab_image_4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/0e091d2b-4cf6-4528-a7ce-0f5510ea6280_image_thumb_1.png" width="454" height="428" /&gt;&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;Once the Page’s DataContext has been set you can change the data binding for any control on the page by simply selecting the property (ex: text, checked, etc) and selecting “&lt;strong&gt;Apply Data Binding…”,&lt;/strong&gt; and setting the Path to LocalizedResources.BtnText or whatever the resource key that you are trying to bind to is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Remember: &lt;/strong&gt;the Application Bar is not a Silverlight control and therefore can’t have resources bound to it in the same way. To achieve this you will have to &lt;a href="http://msdn.microsoft.com/en-us/library/ff637520(v=vs.92).aspx#sectionToggle2"&gt;create or update the Application Bar at runtime.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Wi-Fi Internet browser login problems&lt;/h3&gt;

&lt;p&gt;This is another problem that is far from 100% clear at first. &lt;/p&gt;

&lt;p&gt;Your users will probably come across bad data while connecting to wireless access points that require a browser login (such as a hotel or library). Usually the device should kick up a session of Internet Explorer to take care of this, but there are a number of situations where this won’t help you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When your background task runs to update a tile and the user hasn’t logged in yet. &lt;/li&gt;

  &lt;li&gt;When the user ignores the browser login page or is interrupted while using it (phone call etc.) – this leaves them in a state of “online” but not net connected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quite often these browser-login walls for Wi-Fi will simply return the login page &lt;em&gt;for every request&lt;/em&gt;. This means that you application will think its speaking to the internet (or Twitter or whatever API you are using) but instead will get back bad data or a 3XX redirect response code.&lt;/p&gt;

&lt;p&gt;What does this mean for you?&lt;/p&gt;

&lt;p&gt;It means that when pulling down data from an external internet source, make sure to the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;White defensive code for &lt;em&gt;WebExceptions&lt;/em&gt; such as Try Catch statements (as long as you only catch the exceptions &lt;a href="http://msdn.microsoft.com/en-us/library/3tca6706.aspx" target="_blank"&gt;you are looking for&lt;/a&gt; – not just any exception). &lt;/li&gt;

  &lt;li&gt;If accessing a data source with a known or documented schema (such as a third party XML API), validate returned data against a schema file (in XML’s case, use an XSD to validate the data format before accessing it or deserializing it). This will ensure that even if data is returned, you know its what you were actually looking for.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Always assume the data that your app will be getting back from the internet is invalid.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Network Interface Online Without Internet&lt;/h3&gt;

&lt;p&gt;Another problem that can affect your users and leave them thinking bad things of your app is when their devices &lt;em&gt;think&lt;/em&gt; they are connected to the Network but don’t necessarily have internet access. This can happen in areas of bad coverage, or when their carrier has internet connectivity problems.&lt;/p&gt;

&lt;p&gt;Ensuring that the device has &lt;a href="/blog/2010/12/09/checking-for-network-connectivity-in-windows-phone-7-sdk"&gt;Network connectivity&lt;/a&gt; won’t fix this problem as your app will still timeout if it can’t access the internet.&lt;/p&gt;

&lt;p&gt;There are two ways to minimise this problem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;While your app is running, every few minutes download a small text file, similar to &lt;a href="http://blog.superuser.com/2011/05/16/windows-7-network-awareness/"&gt;Microsoft’s NCSI service&lt;/a&gt; and use this to establish Network Connectivity (you could even use the MS URL to save yourself time). &lt;/li&gt;

  &lt;li&gt;Set timeouts on your app’s network downloads to a lower figure than the default of 100 seconds – the standard Windows Phone 7 SDK &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx" target="_blank"&gt;HttpWebRequest&lt;/a&gt; doesn’t support the Timeout property, so the guys over at &lt;a href="http://wp7contrib.codeplex.com/" target="_blank"&gt;WP7Contrib&lt;/a&gt; have put a nice solution in place for putting Timeouts in place. I put mine at 40 seconds, as this seems to be a good compromise between slow network speeds and users waiting forever – &lt;em&gt;your mileage may vary&lt;/em&gt; so test this until you find a happy medium.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;Overall there are a number of little things that can add polish to your app – often your users may have a totally different experience when using your app in the wild, and the closer we can get to covering all of these things to better – and happy users rate you app highly, and you get more downloads. Either way you look at this it’s a good thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you have any little niggling things you wished you’d kept in mind when first writing your Windows Phone 7 app? I’d love to hear in the comments section below.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UQVpSJ4yU_hk5WTL73Sw_KygqCY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UQVpSJ4yU_hk5WTL73Sw_KygqCY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UQVpSJ4yU_hk5WTL73Sw_KygqCY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UQVpSJ4yU_hk5WTL73Sw_KygqCY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=gYejzGK23MY:yyyOLTYBU8w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=gYejzGK23MY:yyyOLTYBU8w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=gYejzGK23MY:yyyOLTYBU8w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=gYejzGK23MY:yyyOLTYBU8w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/2aNTEc8j9ug" height="1" width="1"/&gt;</description><pubDate>4/2/2012 7:04:13 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/04/02/things-i-missed-so-you-wonrsquot-have-to-ndash-wp7-sdk</feedburner:origLink></item><item><title>Make Your Own Wi-Fi Hotspot - Testing Development Websites on Mobiles and Tablets</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/KDwD8fQq094/make-your-own-wifi--testing-development-websites-on-mobiles-and-tablets</link><description>&lt;p&gt;Often you need to test a website on an tablet device such as an iPad using a local development machine’s web server. For whatever reason the available Wi-Fi when developing your site may be on another subnet or network entirely to you development machine (such as in an office environment). Situations like these call for a bit of creative thinking and a different approach, so if this is a problem you face here’s my take on a possible solution.&lt;/p&gt;  &lt;p&gt;My workplace has pretty strict networking arrangements in place as we work with Banks and government agencies. This is all well and good until you need to develop something for a mobile device and there's no way to connect a smart phone or tablet to your development machine over the network/Wi-Fi. For the guys on our team this is caused by the network subnet that is served over our office Wi-Fi being placed in a DMZ without network access (we don't want&amp;#160; our &lt;a href="http://www.reddit.com/" target="_blank"&gt;Reddit&lt;/a&gt; surfing clients in reception having access to our super secret stuff).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/9a5d374b-e09f-4be8-9575-a90e2e04eccb_image_22.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/e497adae-fa76-49ea-a29d-7f682eff4379_image_thumb_7.png" width="350" height="248" /&gt;&lt;/a&gt;Obviously this causes&amp;#160; my team and I a few productivity roadblocks.&lt;/p&gt;  &lt;p&gt;Working with mobile and tablet websites carry there own set of problems and there is a range of tools available to solve many of these. Some involve device centric visual elements such as CSS (&lt;a href="http://labs.adobe.com/technologies/shadow/" target="_blank"&gt;Adobe Shadow&lt;/a&gt;) and user agent detection (&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/user-agent-switcher/" target="_blank"&gt;user agent switcher&lt;/a&gt;). Coming from a server side development angle I've also blogged before on how to sniff &lt;a href="http://www.diaryofaninja.com/blog/2010/11/09/using-fiddler-to-sniff-mobile-device-application-traffic" target="_blank"&gt;mobile device traffic for debugging&lt;/a&gt; web service traffic on mobile devices. However none of these solutions help solve the largest problem in productivity when it comes to locally developing and testing sites from a developers machine - and if you happen to work in a restricted environment like me and my team then the pain from this problem is a lot stronger. &lt;/p&gt;  &lt;p&gt;With this in mind, speeding up your productivity in this areas leads to big gains. If you can avoid having to deploy your development site over and over just to test something small, then you’ve smashed it out of the park.&lt;/p&gt;  &lt;h3&gt;Don't have Wi-Fi? Now you do!&lt;/h3&gt;  &lt;p&gt;The problem when boiled down is that you need to give the mobile device you are testing on wireless network access to your development machine’s web server. For people developing ASP.net websites this usually means IIS.&lt;/p&gt;  &lt;p&gt;Now a lot of laptops and desktops these days come bundled with a wireless card as standard (this should give you an idea where I’m going with this), but up until Windows 7, Microsoft's networking stack hasn't really had the flexibility to do black magic with wireless cards in the ways that our Linux and OSX cousins have been able to. With the release of &lt;a href="http://www.istartedsomething.com/20090516/windows-7-native-virtual-wifi-technology-microsoft-research/" target="_blank"&gt;Windows 7 this changed&lt;/a&gt; - and with this a light bulb went off in the head of one of the developers now working for &lt;a href="http://www.connectify.me/" target="_blank"&gt;Connectify&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Connectify&lt;/h3&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/aac758f4-c086-461b-8420-4d0b01b46459_image_198a9f99-ca10-4983-8fd6-c9c13ca0ae64.png" width="244" height="51" /&gt;Connectify is a piece of software that enables a Windows PC with a Wi-Fi device to act as a wireless access point. This enables users to share an internet connection between multiple computing devices without the need for a separate physical access point or router.&lt;/p&gt;  &lt;p&gt;This has a whole range of benefits (maybe you are in a hotel using their internet and want your phone or tablet to get access?) but what I'll focus on here is using Connectify to test locally while developing websites.&lt;/p&gt;  &lt;p&gt;It is extremely easy to setup, so lets take a look.&lt;/p&gt;  &lt;h3&gt;What you’ll need&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;A Windows 7 PC (assuming this is a given if you’ve read this far). &lt;/li&gt;    &lt;li&gt;A Wi-Fi Card. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://technet.microsoft.com/en-us/library/cc725762.aspx" target="_blank"&gt;IIS Installed.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Your Visual Studio project &lt;a href="http://msdn.microsoft.com/en-us/library/ms178108.aspx" target="_blank"&gt;setup to use IIS for testing&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Logged in as a user that has local admin rights.&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Setting it up&lt;/h3&gt;  &lt;p&gt;I will use the Empty ASP.Net MVC Project template for this walkthrough simply for familiarities sake; this should work with any site you can run locally. Even ones hosted on another web server like *&lt;strong&gt;&lt;em&gt;shock, horror&lt;/em&gt;&lt;/strong&gt;* Apache or NGINX.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/b0d98ea2-f810-4ca5-8fc9-1b53b8c18907_image_f3ddbe40-42d9-453b-82e5-d976fe405786.png" width="350" height="200" /&gt;&lt;/p&gt;  &lt;p&gt;Firstly as housekeeping, you’ll need to setup a local IIS website that:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Accepts incoming requests on TCP Port 80. &lt;/li&gt;    &lt;li&gt;Serves on all IP addresses (once Connectify is setup, you can get it to simply work on Connectify’s interface/IP Address). &lt;/li&gt;    &lt;li&gt;Points at your website’s root directory (For ASP.net web sites this means the root of your website project.)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you don’t want to install full blown IIS, you can get away with &lt;a href="http://learn.iis.net/page.aspx/868/iis-express-overview/" target="_blank"&gt;IIS Express&lt;/a&gt; instead.&lt;/p&gt;  &lt;p&gt;First, download Connectify from &lt;a href="http://www.connectify.me/" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Run the installer.&lt;/p&gt;  &lt;p&gt;When done you’ll be greeted by this screen, simply click &lt;em&gt;continue.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/e4c90d70-a872-4856-a60b-6c4e9684ca7f_image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/03ebef76-b079-4dea-a0f2-9add076f66c1_image_thumb_1.png" width="350" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You’ll then be asked whether you want to use the “Lite” or “Pro” version of Connectify. Select &lt;em&gt;Lite&lt;/em&gt; as this is all we’ll need.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/195a204d-04da-4171-9d6c-23569f7f1031_image_7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/ff4e9fe4-c4c7-423b-84da-210ca9b96235_image_thumb_2.png" width="350" height="312" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This will leave you with the panel on the right of the screen asking you to setup your HotSpot. &lt;/p&gt;  &lt;p&gt;Enter a HotSpot name (the Lite version requires that the name starts with “&lt;em&gt;Connectify-“&lt;/em&gt;), password (must be 8 characters or over), and then select the internet connection you would like to share.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Even if you don’t work in an environment where security is considered “critical”, make sure that you set a &lt;em&gt;REALLY&lt;/em&gt; strong password. After all, you are setting up an additional way for people to get onto your network so this is a pretty big deal in an office environment. Check out &lt;/font&gt;&lt;a href="http://www.troyhunt.com/2011/08/im-sorry-but-were-you-actually-trying.html" target="_blank"&gt;&lt;font color="#ff0000"&gt;Troy Hunt’s great post on passwords&lt;/font&gt;&lt;/a&gt;&lt;font color="#ff0000"&gt; for easy ways to manage these.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;For me, I am already on Wi-Fi as I'm writing this post on my laptop, but you may want to select a different connection to share – the interface you share doesn’t matter too much as you’ll only be accessing your local IIS installation; as long as you don’t have firewall rules setup on the interface you’ve selected stopping port 80 access you should be fine.&lt;/p&gt;  &lt;p&gt;Then hit the “&lt;em&gt;Start HotSpot”&lt;/em&gt; button.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/b362ebcf-b098-423d-b1d4-d3311da70b0c_image_9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/9ad45ae5-45e6-4a29-95de-6d112cc5c1a8_image_thumb_3.png" width="307" height="628" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now on your mobile device, connect to your newly configured Wireless Access Point by changing the settings on your device’s Wi-Fi connection.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/9adb2030-5ce7-4a84-974e-872cfa93ab60_image_3726e057-859b-423c-bb64-dcc4cf1d9965.png" width="354" height="266" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/58e7fdb7-0020-443c-9719-9788fd3b669f_image_da887fc0-04eb-4cb2-b2bb-2a8a4823b0bc.png" width="354" height="266" /&gt;&lt;/p&gt;  &lt;p&gt;Now on your host machine, open a command prompt window and type “&lt;strong&gt;&lt;em&gt;ipconfig”&lt;/em&gt;&lt;/strong&gt; to pull up the list of interfaces on your machine. You should notice that you now have an &lt;strong&gt;additional&lt;/strong&gt; Wi-Fi adapter – this is the virtual one created by Connectify to serve your devices. Take note of the &lt;em&gt;IP Address&lt;/em&gt; listed, as this will be the address your site is hosted on.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/28f0816a-f2db-4100-b7f5-64a1bc7a162e_image_39bc2238-e7e7-45cb-961c-919605a5ee6e.png" width="350" height="176" /&gt;&lt;/p&gt;  &lt;p&gt;Now enter this address in your device’s browser proceeded by “http://”. This is the IP address of your new virtual Wi-Fi adapter (mine was &lt;a href="http://192.168.96.1"&gt;http://192.168.96.1&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/867cfa1a-65ab-4ec5-8303-b409773f3a9c_image_19.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/ba822646-5a88-483d-a031-d82f05d28fa8_image_thumb_6.png" width="350" height="262" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you have trouble getting this working (your device maybe sits there waiting for the page to load &lt;em&gt;forever&lt;/em&gt;), then Windows Firewall or similar may be blocking the request. You can add IIS to the &lt;em&gt;Allowed List&lt;/em&gt; by going to “&lt;strong&gt;Settings &amp;gt; System and Security &amp;gt; Windows Firewall &amp;gt; Allowed Programs&lt;/strong&gt;” and ticking the box to allow &lt;strong&gt;IIS (World Wide Web Services (HTTP).&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/4e10ba82-d81d-4675-ad46-c75d3d8e3a71_image_17.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/26260262-956c-4183-945f-469859412fb9_image_thumb_5.png" width="350" height="246" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;&lt;font color="#ff0000"&gt;Special Note&lt;/font&gt;&lt;/h3&gt;  &lt;p&gt;When you have finished testing your local website, it is important to click the &lt;em&gt;Stop Hotspot&lt;/em&gt; button in Connectify to turn off your newly created Wi-Fi access point. This will ensure that no evil doers can run any dictionary or rainbow table attacks on your machine while you aren’t expecting it (probably while you are at home over the weekend or overnight).&lt;/p&gt;  &lt;h3&gt;Summary&lt;/h3&gt;  &lt;p&gt;There are now a number of tools available to assist with testing sites on mobiles and tablets, but few tackle the problem at its source as well as this does: speeding up the rinse repeat of a developer test-deploy-modify cycle. Hopefully I've shown you a way to drastically reduce the time spent on this when working locally on your developer machine.&lt;/p&gt;  &lt;p&gt;What tools do you use to help speed up mobile website development? I’d love to hear in the comments below.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AORuZ8wPg6XJYnuI6L4_jsUJ1h4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AORuZ8wPg6XJYnuI6L4_jsUJ1h4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AORuZ8wPg6XJYnuI6L4_jsUJ1h4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AORuZ8wPg6XJYnuI6L4_jsUJ1h4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=3SBIjWQ3hiY:wp8Yfg8Run8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=3SBIjWQ3hiY:wp8Yfg8Run8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=3SBIjWQ3hiY:wp8Yfg8Run8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=3SBIjWQ3hiY:wp8Yfg8Run8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/KDwD8fQq094" height="1" width="1"/&gt;</description><pubDate>4/15/2012 2:50:27 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/04/15/make-your-own-wifi--testing-development-websites-on-mobiles-and-tablets</feedburner:origLink></item><item><title>Cause for Concern - Piracy on Windows Phone 7</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/gCFdmGSWmKs/cause-for-concern--piracy-on-windows-phone-7</link><description>&lt;p&gt;I have been playing with the Windows Phone 7 SDK for a while now, however I have been lucky to still have a day-job while doing my tinkering and therefore haven’t sourced my main income from sales in the WP7 marketplace. There are others who don’t have the same luxury as me and have bet a considerable amount of their time on the platform to date. Whether these developers are aware of it or not they are fighting a silent battle that I want to bring more awareness to –&amp;nbsp; a problem that every smart phone ecosystem has faced to date: Piracy. &lt;/p&gt; &lt;p&gt;&lt;a href="http://arstechnica.com/microsoft/news/2010/12/windows-phone-7-piracy-materializes-with-freemarketplace.ars" target="_blank"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 10px 0px 10px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" border="0" align="right" src="http://static.arstechnica.net/assets/2010/12/winphone7-piracy-ars-thumb-640xauto-18592.jpg" width="350" height="197"&gt;&lt;/a&gt;This problem is a worry as it affects Windows Phone devices more than some other platforms as we write our applications in languages that can easily be decompiled: get an app’s binaries, and you have mapped the apps very genome, its source code. A problem which once done is out there forever – if people get your app’s code or resources now, the game is up even if Microsoft releases a fix in the future. Hopefully by raising more awareness of this, together we can challenge Microsoft to put more effort into this area moving forward.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;NOTE:&lt;br&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;I need to be really clear before I start. This post does not promote piracy on the Windows Phone 7 platform. I personally develop apps for Windows Phone 7 and have a vested interest in the platform’s success. Hiding facts that are publically available does not increase this behaviour but it definitely brings it out of the shadows for all to see (and implement change).&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;What&lt;strong&gt;&lt;em&gt; &lt;/em&gt;&lt;/strong&gt;I&lt;strong&gt;&lt;em&gt; am&lt;/em&gt;&lt;/strong&gt; trying to do is bring up a topic that is not a new one for Windows Phone but appears to have been un-addressed by Microsoft &lt;a href="http://www.wpcentral.com/windows-phone-marketplace-app-security-cracked-proof-of-concept-video" target="_blank"&gt;since&lt;/a&gt; &lt;a href="http://www.youtube.com/watch?v=flqB9WCkGiQ&amp;amp;feature=player_embedded" target="_blank"&gt;2010&lt;/a&gt;. This issue can’t go away until more effort is made in this area or the problem will only get worse as time goes on&lt;/font&gt;&lt;font color="#ff0000"&gt;.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;On a side note, I also tried to contact a number of people at Microsoft to get their view before posting this post however, after a week or trying, I am yet to hear from anyone.&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;What this post will cover:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Piracy on Windows Phone 7: It exists, and more attention needs to be given to it.  &lt;li&gt;How to pirate a Windows Phone 7 app.  &lt;li&gt;A closer look at how the piracy app I'm using works.  &lt;li&gt;What can you as a developer do about this problem on your apps.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Piracy on Windows Phone 7&lt;/h3&gt; &lt;p&gt;All of the smartphone “walled gardens” share one thing: Piracy. Apple being the leader in this space with the iOS platform and knows this better than any of us; People have been pirating iPhone games for years with some stats showing that for every app sold 10 more are pirated on the IOS platform.&lt;/p&gt; &lt;p&gt;Windows phone 7 has been no different, with &lt;a href="http://www.wpcentral.com/windows-phone-marketplace-app-security-cracked-proof-of-concept-video" target="_blank"&gt;WP Central reporting&lt;/a&gt; that piracy was easily achievable way back in 2010. There have been many such reports since &lt;a href="http://mobilitydigest.com/tool-to-download-and-pirate-wp7-apps-is-out-dont-use-it/" target="_blank"&gt;then&lt;/a&gt;. There is still little or no blocks in someone’s way from firstly side loading apps easily onto devices (be they pirated or not) or more worryingly simply sniffing the Zune traffic and then downloading the XAP directly from Microsoft. It’s now nearly 2 years since this news first came to light and little appears to have changed; there are still apps out there that enable these same hacks to be conducted easily by the everyday lay person.&lt;/p&gt; &lt;p&gt;My large concern about this is the double whammy that is Piracy on WP7 - iOS apps are built in objective-c, which while not making iOS apps &lt;a href="http://stackoverflow.com/questions/2334072/decompiling-objective-c-libraries" target="_blank"&gt;immune to decompilation&lt;/a&gt;; it does make the act of decompiling a lot more challenging for any would be pirates. &lt;/p&gt; &lt;p&gt;Windows Phone 7 apps don’t have anywhere near this level of complexity when it comes to decompiling the source code and assets that a game or app is made with. We build our apps using the .Net framework in any of its supported languages, which in turn gets compiled into an intermediate language (MSIL) that by its very nature is powerful because it’s not low level.&lt;/p&gt; &lt;p&gt;As I'm sure you are all aware, If you get a .Net framework assembly (.dll) and arm yourself with on of the &lt;a href="http://www.jetbrains.com/decompiler/" target="_blank"&gt;multitude&lt;/a&gt; &lt;a href="http://wiki.sharpdevelop.net/ILSpy.ashx" target="_blank"&gt;of&lt;/a&gt; &lt;a href="http://www.reflector.net/" target="_blank"&gt;decompilers&lt;/a&gt; on the open web, you very soon have a readable copy of a binary’s source code.&lt;/p&gt; &lt;p&gt;If you are a Windows Phone 7 developer this is all a little unnerving when you consider how much time and effort you’ve poured into your app.&lt;/p&gt; &lt;p&gt;Taking a closer look at the facts:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Device owners can easily unlock their phones for side loading fun both legally and using hacks (even if semi legitimately done with something like &lt;a href="http://www.chevronwp7.com/" target="_blank"&gt;ChevronWP7&lt;/a&gt;).  &lt;li&gt;Getting an unadulterated copy of an application or game’s XAP file is &lt;a href="http://withwindows.com/download-windows-phone-7-apps-xap-directly-pc-zune/" target="_blank"&gt;trivial&lt;/a&gt; (more on this in a sec).  &lt;li&gt;Once anyone has the XAP for your app, they can then easily grab your source code and resources, further allowing them to do what they want with it. Side load it for free, or extract your app’s resources for nefarious purposes.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;My concern grows when I consider that in the last year there have been instances where pirates have downloaded an app’s XAP from the Windows Phone 7 marketplace, created a developer account and &lt;a href="http://www.ijunkey.com/microsoft-automatically-removes-pirated-app-from-windows-phone/" target="_blank"&gt;submitted the same app themselves&lt;/a&gt; (with Microsoft approving it). There has also been a case where pirates have downloaded an App, &lt;a href="http://apps-are-people-too.blogspot.com.au/2012/01/hoisted-by-my-own-petard-or-why-my-app_09.html" target="_blank"&gt;copied its contents and created a competing app&lt;/a&gt; with the original developers resources (in this case their Yoga video content, created by their wife…).&lt;/p&gt; &lt;p&gt;There is little we can do about the first or third step mentioned above, but I think Microsoft can do more about the second item – the ease of getting an apps package.&lt;/p&gt; &lt;h3&gt;Is this really a problem?&lt;/h3&gt; &lt;p&gt;Over the last few days I have been touching base with a few people in the community about this. Many have said similar things: prove this is a problem, and we’ll give it more thought.&lt;/p&gt; &lt;p&gt;One comment from &lt;a href="https://twitter.com/JustinAngel" target="_blank"&gt;Justin Angel&lt;/a&gt; (a Nokia principal engineer on WP7) said this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/116a3600-d5a2-4d3a-a2f6-ccffb4e41535_image_42fc833b-dfcb-4fb6-a34b-6097eacf5b2d.png" width="518" height="93"&gt;&lt;/p&gt; &lt;p&gt;While I must apologise before I go on in reply to Justin’s comment, as I’m not beating up on him personally, the view he mentions on piracy as “Prove it’s a problem” for a relatively new platform like Windows Phone is dead wrong.&lt;/p&gt; &lt;p&gt;If as developers we pour part of our lives into creating apps for a smart phone platform, we are often choosing to do so over another. If there is a feeling that the creators of your chosen platform care little for the security of your intellectual property, that’s a pretty good reason to not bother with it. This is especially the case with Windows Phone where it is so easy to reverse engineer an app to retrieve the app’s IP.&lt;/p&gt; &lt;p&gt;Justin’s stance does nothing to support the developers choice for Windows Phone 7 or allay any fears of current developers on the platform.&lt;/p&gt; &lt;p&gt;If I can download my app’s XAP and open it as a zip file this is what I see:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/7e19ad09-6984-4874-a644-f2596fcc2ae9_image_71a9cf9e-1303-440a-bea0-60306b6add53.png" width="350" height="280"&gt;&lt;/p&gt; &lt;p&gt;if I then decompile one of these binaries this is what I see… real code (if you haven’t obfuscated your apps code):&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;InTheKnow.PhoneApplication
{
  &lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MainViewModel &lt;/span&gt;: INotifyPropertyChanged
  {
    &lt;span style="color: blue"&gt;private &lt;/span&gt;PropertyChangedEventHandler PropertyChanged;

    &lt;span style="color: blue"&gt;public &lt;/span&gt;ObservableCollection&amp;lt;GoogleAnalyticsAccount&amp;gt; Accounts { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;private set&lt;/span&gt;; }

    &lt;span style="color: blue"&gt;public bool &lt;/span&gt;IsDataLoaded { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;set&lt;/span&gt;; }

    &lt;span style="color: blue"&gt;public bool &lt;/span&gt;IsFirstTimeLoad { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;set&lt;/span&gt;; }
  }
&lt;/pre&gt;
&lt;p&gt;This means that anyone getting my app potentially has my IP – whether the numbers of piracy are high today or not, this is a problem.&lt;/p&gt;
&lt;h3&gt;What the bad guys keep on the down low&amp;nbsp; &lt;/h3&gt;
&lt;p&gt;If you do a Google search looking for Windows Phone 7 pirating, you’ll soon come across a few Windows desktop apps floating around that make the act trivial. I will not name them or link to them, but I will walk you through using one of them to download my personally developed Google Analytics app &lt;a href="http://intheknowapp.com/" target="_blank"&gt;InTheKnow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have downloaded an app I found that touts itself as being a &lt;em&gt;one stop shop&lt;/em&gt; for Windows Phone 7 pirating. It downloads, removes security and side loads all in one.&lt;/p&gt;
&lt;p&gt;I have blocked out any branding from the screenshot below to make it harder for budding pirates reading this post to find it, but you can see from its interface that when I search for my app that it offers a similar experience to that of the Zune Marketplace client (I can only assume it uses the same web service endpoints).&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/149876ac-c600-4914-a0e1-11100ef25342_image_43e5c17d-0a47-41fc-b886-626608f27726.png" width="350" height="290"&gt;&lt;/p&gt;
&lt;p&gt;Once I’ve search for my app and found the version that I want, a simple double-click is all that is needed to download it.&lt;/p&gt;
&lt;p&gt;I decided at this point to do a little digging to see what the creators of this app were doing that was magical enough to get around my perception of the security Microsoft would have put in place for the marketplace.&lt;/p&gt;
&lt;p&gt;Taking a look at this user journey using &lt;a href="http://fiddler2.com/fiddler2/" target="_blank"&gt;Fiddler&lt;/a&gt;, I became quite concerned.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.diaryofaninja.com/asset/blogimages/10def8a1-01f0-41e2-b28d-4bd9fba692e1_image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/69a296c5-6e23-4285-937b-c6b431847f58_image_thumb_1.png" width="354" height="194"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;None of the traffic coming or going was over HTTPS, and none of it consisted of anything but plain vanilla Http GET calls.&lt;/p&gt;
&lt;p&gt;The app queries the Zune store using a search URL, which in turn returns a GUID along with all the store details for an app.&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/00ba3f82-05bd-4f9b-a4e1-7bca8c39d840_image_ee355dba-9456-4bde-b22f-bfbf5e413cfd.png" width="500" height="40"&gt;&lt;/p&gt;
&lt;p&gt;It then queries another URL using the returned app GUID, which returns XML containing the download URL for the app’s package.&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/3fa6c372-26ae-4293-909d-83528e5eb0b6_image_53340edd-130a-439b-9035-572fa6244aa8.png" width="500" height="57"&gt;&lt;/p&gt;
&lt;p&gt;If you copy and paste this last &lt;strong&gt;raw URL&lt;/strong&gt; into a freshly started web browser (i.e. no session, no special headers), this downloads &lt;u&gt;without hesitation&lt;/u&gt;. It’s just a plain old URL – you could email it or share it just the same.&lt;/p&gt;
&lt;p&gt;The XAP you download only has one protection to it – an XML file that contains a signing signature. Something that you can find an easy way around with the help of another Google search – hell, the marketplace piracy tool I was using to write this post even would patch this for you upon download! How convenient…! *sarcasm*&lt;/p&gt;
&lt;p&gt;Again to reiterate, all of the simple things Microsoft could have done:&lt;/p&gt;
&lt;p&gt;No authentication occurs.&lt;/p&gt;
&lt;p&gt;SSL is not used.&lt;/p&gt;
&lt;p&gt;No special headers or HTTP tricks are used.&lt;/p&gt;
&lt;p&gt;And that was that. I now had the XAP file for my app, without paying. And as only a cursory Google search will tell you, XAP’s aren’t hard to get the contents of – they are just zip files.&lt;/p&gt;
&lt;h3&gt;But you have to put it on your phone still, right?&lt;/h3&gt;
&lt;p&gt;At this point regardless of the fact that I now have the binaries and resources for my app (i.e everything there is to my app), if I was to side load this app on my phone I’d still need to have a developer registered phone, so that’s a hurdle right?&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/ad1706a9-1e50-4ca2-816e-13a19e2225b1_image_4541fc15-d111-4316-ac14-fed62dc06ba1.png" width="354" height="232"&gt;&lt;/p&gt;
&lt;p&gt;Wrong – the application I was using kindly came with a XAP uploader as well that works with non-developer unlocked devices. Two more clicks and I was done.&lt;/p&gt;
&lt;h3&gt;This sucks! What do I do to protect my apps&lt;/h3&gt;
&lt;p&gt;So Microsoft might not have the answers yet to the piracy problem, but there &lt;em&gt;are&lt;/em&gt; things you can do to attempt to minimise the damage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Obfuscate your code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Microsoft has teamed up with &lt;a href="http://www.preemptive.com/products/dotfuscator/overview" target="_blank"&gt;PreEmptive Solutions&lt;/a&gt; to package the Community Edition of their code obfuscation tool “&lt;strong&gt;DotFuscator&lt;/strong&gt;” with Visual Studio. Pre-emptive has also released a full blown Windows Phone Version that is also free and can be downloaded from &lt;a href="http://www.preemptive.com/know-more/windows-phone-7" target="_blank"&gt;here&lt;/a&gt; that includes support for Silverlight XAML obfuscation as well.&lt;/p&gt;
&lt;p&gt;These tools obfuscate the code in your binaries, so that once the bad guys get your XAP file they will find it harder to understand any code they decompile – any resources such as videos or images will still remain free to copy or edit though so keep this in mind.&lt;/p&gt;
&lt;p&gt;It is worth noting that some obfuscation tools often &lt;em&gt;can and do&lt;/em&gt; slow your app down.&lt;/p&gt;
&lt;p&gt;Example of your code before Obfuscation:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;CalcPayroll(&lt;span style="color: #2b91af"&gt;SpecialList &lt;/span&gt;employeeGroup) {
    &lt;span style="color: blue"&gt;while &lt;/span&gt;(employeeGroup.HasMore()) {
        &lt;span style="color: blue"&gt;var &lt;/span&gt;employee = employeeGroup.GetNext(&lt;span style="color: blue"&gt;true&lt;/span&gt;);
        employee.UpdateSalary();
        DistributeCheck(employee);
    }
}
&lt;/pre&gt;
&lt;p&gt;Example of your code after using &lt;a href="http://www.preemptive.com/know-more/windows-phone-7" target="_blank"&gt;Dotfuscator&lt;/a&gt;:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;a(&lt;span style="color: #2b91af"&gt;a &lt;/span&gt;b)
{
    &lt;span style="color: blue"&gt;while &lt;/span&gt;(b.a())
    {
        a = b.a(&lt;span style="color: blue"&gt;true&lt;/span&gt;);
        a.a();
        a(a);
    }
}&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;My advice: Obfuscate every app you submit to the marketplace.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.diaryofaninja.com/asset/blogimages/18e110a3-cdc2-47d4-9db5-9ad0ceaafd34_image_100c66a8-d42e-4b72-b291-f2c0c710d753.png" width="354" height="232"&gt;&lt;/p&gt;
&lt;h3&gt;Code checks&lt;/h3&gt;
&lt;p&gt;Some developers are using code that looks for the presence of &lt;a href="http://www.windowsphonegeek.com/tips/PROTECT-YOUR-Windows-Phone-APP-AGAINST--casual--PIRACY" target="_blank"&gt;DRM files in the app’s directory&lt;/a&gt; and if missing, launches the marketplace to purchase. &lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static bool &lt;/span&gt;IsHacked()
{
    &lt;span style="color: blue"&gt;try
    &lt;/span&gt;{
        &lt;span style="color: blue"&gt;#if &lt;/span&gt;DEBUG
                &lt;span style="color: gray"&gt;return false;
        &lt;/span&gt;&lt;span style="color: blue"&gt;#endif
 
        &lt;/span&gt;&lt;span style="color: green"&gt;//scramble WMAppPRHeader.xml file name to make life a little harder in case of reverse engineering
        &lt;/span&gt;&lt;span style="color: blue"&gt;string &lt;/span&gt;fl = &lt;span style="color: #a31515"&gt;"xxxWxxxxMxxxxAxxxxpxxxpxxxPxRxxxxxHxxxxxxxexxxxxxaxxxxdxxxxxxxxerxxxxx"&lt;/span&gt;;
        fl = fl.Replace(&lt;span style="color: #a31515"&gt;"x"&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;.Empty) + &lt;span style="color: #a31515"&gt;".&lt;/span&gt;&lt;span style="color: #a31515"&gt;x&lt;/span&gt;&lt;span style="color: #a31515"&gt;m&lt;/span&gt;&lt;span style="color: #a31515"&gt;l"&lt;/span&gt;;
        &lt;span style="color: #2b91af"&gt;XDocument &lt;/span&gt;doc = &lt;span style="color: #2b91af"&gt;XDocument&lt;/span&gt;.Load(fl); &lt;span style="color: green"&gt;//is hacked, this file is missing or empty!!!
        &lt;/span&gt;&lt;span style="color: blue"&gt;return false&lt;/span&gt;;
    }
    &lt;span style="color: blue"&gt;catch &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Exception&lt;/span&gt;)
    {
        &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;"This app was pirated and is not safe to use, please download the original one from Marketplace."&lt;/span&gt;);
        &lt;span style="color: blue"&gt;var &lt;/span&gt;marketplaceDetailTask = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MarketplaceDetailTask
                                        &lt;/span&gt;{
                                            ContentIdentifier =
                                                &lt;span style="color: #2b91af"&gt;PhoneHelper&lt;/span&gt;.GetAppAttribute(&lt;span style="color: #a31515"&gt;"ProductID"&lt;/span&gt;).Replace(&lt;span style="color: #a31515"&gt;"{"&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;.Empty).
                                                Replace(&lt;span style="color: #a31515"&gt;"}"&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;.Empty).Trim(),
                                            ContentType = &lt;span style="color: #2b91af"&gt;MarketplaceContentType&lt;/span&gt;.Applications
                                        };
        &lt;span style="color: green"&gt;//ProcutdID will be changed after AppHub certification, so has to be read from manifest!

        //download Coding4Fun toolkit for this helper
        &lt;/span&gt;marketplaceDetailTask.Show();
  
        &lt;span style="color: blue"&gt;return true&lt;/span&gt;;
     }
}&lt;/pre&gt;
&lt;p&gt;You could consider the implementation of these techniques, but be warned: This can be touch and go as you risk making your application non-functional if Microsoft changes their DRM functionality or something out of the ordinary happens in the legitimate deployment of your app.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;We cannot stick our heads in the sand any longer – if you are a member of the Windows Phone 7 team and are reading this, please help me raise this with your team members. I love the platform and want it to continue, but as a developer I need assurances that these things will get attention – not take years to fix as they appear to have to date.&lt;/p&gt;
&lt;p&gt;A web service similar to the one suggested &lt;a href="http://forums.create.msdn.com/forums/p/70966/432948.aspx" target="_blank"&gt;here&lt;/a&gt;, would be a great active validation technique that should limit the amount of effort the WP7 team put into it.&lt;/p&gt;
&lt;p&gt;If Microsoft wants developers to invest time and money in creating apps for their platform, they have to have a good story when it comes to Piracy – currently this doesn’t appear to be the case.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_VYaZyILdKOVsqudoVfl2u3OkvE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_VYaZyILdKOVsqudoVfl2u3OkvE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_VYaZyILdKOVsqudoVfl2u3OkvE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_VYaZyILdKOVsqudoVfl2u3OkvE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=DEUbOOY5qmk:4alpP8xvSYE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=DEUbOOY5qmk:4alpP8xvSYE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=DEUbOOY5qmk:4alpP8xvSYE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=DEUbOOY5qmk:4alpP8xvSYE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/gCFdmGSWmKs" height="1" width="1"/&gt;</description><pubDate>4/25/2012 5:51:54 AM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/04/25/cause-for-concern--piracy-on-windows-phone-7</feedburner:origLink></item><item><title>Come One, Come All to DDD Sydney – June 30th</title><link>http://feedproxy.google.com/~r/DiaryOfANinja/~3/gX9syC8syKc/come-one-come-all-to-ddd-sydney-ndash-june-30th-2012</link><description>&lt;p&gt;I’ve written about local conferences a few times before, but DDD Sydney is &lt;a href="/blog/2011/06/15/developerdeveloperdeveloper-sydney-ndash-2nd-and-3rd-july-2011" target="_blank"&gt;one of my favourites&lt;/a&gt;. There are few conferences that are so “For Us By Us” as &lt;a href="http://www.dddsydney.com" target="_blank"&gt;DDD Sydney&lt;/a&gt; as it’s organised by &lt;a href="http://www.lewisbenge.net/" target="_blank"&gt;Lewis Benge&lt;/a&gt; and contributed to by a whole swath of the local developer community from a number of different user groups, so it’s a great place to come down and meet a number of your local devs, learn something new or take part in the discussions – and for $25 it’s one of the cheapest conference tickets around!&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://www.diaryofaninja.com/asset/blogimages/3f79c2dd-d366-4cf1-aeb7-199e6fce8103_image_d384f2e6-5397-4abf-8fe3-d07ceb66d222.png" width="190" height="97"&gt;&lt;/p&gt; &lt;p&gt;Details:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dddsydney.com/"&gt;http://www.dddsydney.com/&lt;/a&gt; (ONLY AU$25!!!!)&lt;/p&gt; &lt;p&gt;Agenda being voted on now:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dddsydney.com/Voting.aspx"&gt;http://www.dddsydney.com/Voting.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;A number of fellow bloggers from the Sydney scene will being there, so remember to stop by an say hi (&lt;a href="http://www.troyhunt.com/" target="_blank"&gt;Troy Hunt&lt;/a&gt;, &lt;a href="http://www.richard-banks.org/" target="_blank"&gt;Richard Banks&lt;/a&gt;, &lt;a href="http://gurustop.net" target="_blank"&gt;Mohamed Meligy&lt;/a&gt;, and many others).&lt;/p&gt; &lt;h3&gt;Vote for my talk!&lt;/h3&gt; &lt;p&gt;This year is special for me at DDD, as I have submitted a talk to DDD for the first time (go &lt;a href="http://www.dddsydney.com/Voting.aspx" target="_blank"&gt;here&lt;/a&gt; and vote for me, please!).&lt;/p&gt; &lt;p&gt;My talk is titled: &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;A few things Developer's should know about the Internet (But probably don't)(Level: 200 )&lt;/p&gt; &lt;p&gt;Doug Rathbone teaches us that although we can search high and low for the next big thing in programming, often knowing a bit more about how our apps and websites talk on the internet pays dividends. Come take a look at some tips on using TCP/IP, DNS, and Email that will give your next project the edge.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I’m basically going to take you on a journey of a range of points from my posts about TCP/IP, &lt;a href="http://www.diaryofaninja.com/blog/2011/09/27/what-all-good-web-developers-should-know-about-sending-email" target="_blank"&gt;Email Deliverability&lt;/a&gt; and &lt;a href="http://www.diaryofaninja.com/blog/2012/03/03/devops-dns-for-developers-ndash-now-therersquos-no-excuse-not-to-know" target="_blank"&gt;DNS&lt;/a&gt; as well as how it all fits together. My inspiration for this has come from my travels in our industry and the realisation that a lot of us miss a lot of knowledge about what goes on behind the veil of the internet. Hopefully&amp;nbsp; you’ll learn a little bit about how the internet works so that you get home earlier, and your clients are happier. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;I can 1000%* Guarantee that you will love my talk, so tell your friends and family to vote for it!&lt;/strong&gt;&lt;/p&gt; &lt;h5&gt;*not a guarantee.&lt;/h5&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fQQyMYiPbu0DatVcdgonuf_B26U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fQQyMYiPbu0DatVcdgonuf_B26U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fQQyMYiPbu0DatVcdgonuf_B26U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fQQyMYiPbu0DatVcdgonuf_B26U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=u17KXYW43yQ:CXG6IVs1pQk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=u17KXYW43yQ:CXG6IVs1pQk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/DiaryOfANinja?a=u17KXYW43yQ:CXG6IVs1pQk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DiaryOfANinja?i=u17KXYW43yQ:CXG6IVs1pQk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DiaryOfANinja/~4/gX9syC8syKc" height="1" width="1"/&gt;</description><pubDate>5/12/2012 9:38:13 PM</pubDate><feedburner:origLink>http://www.diaryofaninja.com/blog/2012/05/12/come-one-come-all-to-ddd-sydney-ndash-june-30th-2012</feedburner:origLink></item></channel></rss>

