<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3643710353807395912</id><updated>2012-01-28T13:01:47.977-08:00</updated><category term='PDC 09'/><category term='Random'/><category term='Atmosphere'/><category term='Visual Studio'/><category term='Domain Driven Design'/><category term='jQuery'/><category term='Git'/><category term='Test Driven Development'/><category term='WCF'/><category term='SQL CDC'/><category term='Linq to SQL'/><category term='Github'/><category term='Ajax'/><category term='Ninject'/><category term='ASP.NET MVC'/><title type='text'>MrDustpan</title><subtitle type='html'>code and stuff</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7247151202354734767</id><published>2011-09-02T18:57:00.001-07:00</published><updated>2011-09-02T18:58:59.640-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><title type='text'>Git + Dropbox = Crazy Delicious</title><content type='html'>&lt;p&gt;Here’s a nifty trick I learned from a &lt;a href="http://tekpub.com/"&gt;Tekpub&lt;/a&gt; video:&amp;#160; Use git to push your stuff to a dropbox folder on your machine.&amp;#160; That folder is the “master” repository and then it’s automatically synched with Dropbox.&amp;#160; You can even share it with other people if you’d like.&amp;#160; Here’s how (in git bash):&lt;/p&gt;  &lt;pre class="brush: plain;"&gt;cd c:/dev/projects/theAwesome
git init
git add .
git commit -am &amp;quot;initial commit&amp;quot;
mkdir c:/dropbox/repos/theAwesome
git remote add origin c:/dropbox/repos/theAwesome
cd c:/dropbox/repos/theAwesome
git init --bare
cd c:/dev/projects/theAwesome
git push origin master&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7247151202354734767?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7247151202354734767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7247151202354734767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7247151202354734767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7247151202354734767'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2011/09/git-dropbox-crazy-delicious.html' title='Git + Dropbox = Crazy Delicious'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-1428596409105694244</id><published>2011-01-24T18:34:00.001-08:00</published><updated>2011-01-24T18:34:30.030-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>How to Bin Deploy an ASP.NET MVC 3 App</title><content type='html'>&lt;p&gt;If you need to deploy an MVC 3 application to a server that doesn’t have MVC 3 installed in the GAC, it’s pretty easy to do:&lt;/p&gt;  &lt;h3&gt;1. Add References&lt;/h3&gt;  &lt;p&gt;Add the following references to your project:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Microsoft.Web.Infrastructure &lt;/li&gt;    &lt;li&gt;System.Web.Razor &lt;/li&gt;    &lt;li&gt;System.Web.WebPages.Deployment &lt;/li&gt;    &lt;li&gt;System.Web.WebPages.Razor &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h3&gt;2. Set References to “Copy Local”&lt;/h3&gt;  &lt;p&gt;Set “Copy Local” to true for the following references:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Microsoft.Web.Infrastructure &lt;/li&gt;    &lt;li&gt;System.Web.Helpers &lt;/li&gt;    &lt;li&gt;System.Web.Mvc &lt;/li&gt;    &lt;li&gt;System.Web.Razor &lt;/li&gt;    &lt;li&gt;System.Web.WebPages &lt;/li&gt;    &lt;li&gt;System.Web.WebPages.Deployment &lt;/li&gt;    &lt;li&gt;System.Web.WebPages.Razor &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h3&gt;3. Setup URL Rewriting for Virtual Directories&lt;/h3&gt;  &lt;p&gt;You only need to do this if you are deploying to a virtual directory.&amp;#160; Say you are deploying to the sub-domain “turtles.mrdustpan.com”, which actually corresponds to a “turtles” virtual directory.&amp;#160; Without the following URL rewrite, your MVC URLs would look like:&amp;#160; turtles.mrdustpan.com/turtles/Home/Index&amp;#160; instead of turtles.mrdustpan.com/Home/Index.&lt;/p&gt;  &lt;p&gt;To rewrite the URLs, add this to the system.webServer section of your web.config:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;system.webServer&amp;gt;
    &amp;lt;rewrite&amp;gt;
      &amp;lt;rules&amp;gt;
          &amp;lt;rule name=&amp;quot;Remove Virtual Directory&amp;quot;&amp;gt;
              &amp;lt;match url=&amp;quot;.*&amp;quot; /&amp;gt;
              &amp;lt;action type=&amp;quot;Rewrite&amp;quot; url=&amp;quot;{R:0}&amp;quot; /&amp;gt;
          &amp;lt;/rule&amp;gt;
      &amp;lt;/rules&amp;gt;
    &amp;lt;/rewrite&amp;gt;
&amp;lt;/system.webServer&amp;gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-1428596409105694244?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/1428596409105694244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=1428596409105694244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1428596409105694244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1428596409105694244'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2011/01/how-to-bin-deploy-aspnet-mvc-3-app.html' title='How to Bin Deploy an ASP.NET MVC 3 App'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-5067522435849020175</id><published>2011-01-06T16:38:00.001-08:00</published><updated>2012-01-27T08:05:35.655-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Atmosphere'/><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='Github'/><title type='text'>My Git Cheat Sheet</title><content type='html'>Here’s a nice little cheat sheet of the most common commands I’ve been using in Git, to push my changes out to Github:&lt;br /&gt;
&lt;br /&gt;
&lt;table border="0" cellpadding="2" cellspacing="0" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px;"&gt;&lt;tbody&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;cd /c/dev/projects&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;change directory to c:\dev\projects&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git status&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;get the status of current directory&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git add .&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;stage all pending adds/updates&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git add -u&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;stage all pending updates/deletes&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git commit –m "my message"&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;commit the changes with a message&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git push origin master&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;push the committed changes to github&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git branch myBranch&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;create a new branch named “myBranch”&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git branch&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;list all existing branches&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git checkout myBranch&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;switch to the “myBranch” branch&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git checkout master&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;switch to the “master” branch&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;span style="font-family: Consolas;"&gt;git merge myBranch&lt;/span&gt;&lt;/td&gt;          &lt;td valign="top" width="317"&gt;&lt;em&gt;merge “myBranch” into the current branch&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;a href="http://lh5.ggpht.com/_Ibq67iO0TPU/TSZgeZcJRvI/AAAAAAAAAKU/r9TYY2enc6U/s1600-h/cheatsheet%5B2%5D.png"&gt;&lt;img alt="cheatsheet" border="0" height="244" src="http://lh5.ggpht.com/_Ibq67iO0TPU/TSZgewbj-AI/AAAAAAAAAKY/xoGpIPRhInA/cheatsheet_thumb.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="cheatsheet" width="187" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-5067522435849020175?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/5067522435849020175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=5067522435849020175' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/5067522435849020175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/5067522435849020175'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2011/01/my-git-cheat-sheet.html' title='My Git Cheat Sheet'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_Ibq67iO0TPU/TSZgewbj-AI/AAAAAAAAAKY/xoGpIPRhInA/s72-c/cheatsheet_thumb.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-3229045663023350243</id><published>2010-12-14T19:35:00.001-08:00</published><updated>2010-12-15T05:09:27.025-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Atmosphere'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Ninject'/><title type='text'>Ninject with ASP.NET MVC 3…Easy As 1, 2, 3</title><content type='html'>&lt;ol&gt;&lt;li&gt;Add references to Ninject.dll and Ninject.Web.Mvc.dll (You can use NuGet to add Ninject, but for now you’ll have to &lt;a href="https://github.com/ninject/ninject.web.mvc"&gt;download&lt;/a&gt; and build Ninject.Web.Mvc yourself). &lt;/li&gt;
&lt;li&gt;Create 1 or more modules:      &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml;"&gt;public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind&amp;lt;IFoo&amp;gt;().To&amp;lt;Foo&amp;gt;();
    }
}
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Make your HttpApplication (typically global.asax.cs) extend NinjectHttpApplication and override the CreateKernel() method:      &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp;"&gt;public class MvcApplication : NinjectHttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

    protected override IKernel CreateKernel()
    {
        return new StandardKernel(new MyModule());
    }
}&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;That’s it.&amp;#160; Now you’re all set to go, even your controllers will be created with Ninject which means all of their dependencies will be resolved using your Module(s).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-3229045663023350243?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/3229045663023350243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=3229045663023350243' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3229045663023350243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3229045663023350243'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/12/ninject-with-aspnet-mvc-3easy-as-1-2-3.html' title='Ninject with ASP.NET MVC 3…Easy As 1, 2, 3'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7467077723377055894</id><published>2010-11-18T20:13:00.001-08:00</published><updated>2010-11-18T20:13:55.686-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Atmosphere'/><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='Github'/><title type='text'>Setting Up Git</title><content type='html'>&lt;p&gt;I’ve never used Git (or any &lt;a href="http://en.wikipedia.org/wiki/Distributed_revision_control_system"&gt;distributed revision control system&lt;/a&gt;) before, so I thought this would be a good opportunity to get my hands dirty.&amp;#160; I found a few really helpful resources:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://gitref.org/"&gt;Git Reference&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.lostechies.com/blogs/jason_meridth/archive/2009/06/01/git-for-windows-developers-git-series-part-1.aspx"&gt;Git for Windows Developers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://github.com"&gt;Github.com&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Rather than rehash what these resources wonderfully describe in detail, I’ll just summarize the steps I went through to get msysgit up and running and setting up the repository on Github.&amp;#160; As I said, I’ve never used Git before and I am certainly no expert, so hopefully I won’t get any of the terms wrong.&lt;/p&gt;  &lt;h4&gt;Installing msysgit&lt;/h4&gt;  &lt;p&gt;For this I pretty much followed Jason’s instructions step by step for installing msysgit on Windows:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://code.google.com/p/msysgit/downloads/list"&gt;Download&lt;/a&gt; the latest version. &lt;/li&gt;    &lt;li&gt;Run through the installation steps. &lt;/li&gt;    &lt;li&gt;Run Git Bash from the start menu and set the global user.email and user.name settings:&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;&lt;font face="Courier New"&gt;git config --global user.email &lt;/font&gt;&lt;font face="Courier New"&gt;my@email.com&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;git config --global user.name “Your Name”&lt;/font&gt;&lt;/li&gt;   &lt;/ol&gt;    &lt;li&gt;Generate an SSH key pair:&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;&lt;font face="Courier New"&gt;ssh-keygen –C “&lt;/font&gt;&lt;font face="Courier New"&gt;my@email.com&lt;/font&gt;&lt;font face="Courier New"&gt;” –t rsa&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;Press enter when prompted on file location, and twice more for both pass phrase questions.&lt;/li&gt;   &lt;/ol&gt;    &lt;li&gt;Right-click on the folder where the project source will live and select “Git Bash here”.&lt;/li&gt;    &lt;li&gt;In the Git Bash console, type: &lt;font face="Courier New"&gt;git init&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Setting up Github&lt;/h4&gt;  &lt;p&gt;I want to use Github as the central host for my code.&amp;#160; It’s pretty easy to do (&lt;a href="http://help.github.com/"&gt;Github’s help&lt;/a&gt; is also very…helpful):&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create a Github account. &lt;/li&gt;    &lt;li&gt;Go to your account settings and click on “SSH Public Keys” and then “Add another public key”. &lt;/li&gt;    &lt;li&gt;Open the public key file that was generated above and paste the contents into the Key field. &lt;/li&gt;    &lt;li&gt;Create the Atmosphere repository in Github. &lt;/li&gt;    &lt;li&gt;Follow the steps on the next page to initialize a local folder as a Git repository. &lt;/li&gt;    &lt;li&gt;Create some files. &lt;/li&gt;    &lt;li&gt;Create a .gitignore file by typing &lt;font face="Courier New"&gt;touch .gitignore&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Add ignored folders and files to the .gitignore file (such as obj and bin).&lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;git status&lt;/font&gt; to see status of changed/added files.&lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;git add .&lt;/font&gt; to “stage” the files. &lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;git commit&lt;/font&gt; to commit the changes. &lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;git remote add origin &lt;a href="mailto:git@github.com:MrDustpan/Atmosphere.git"&gt;git@github.com:MrDustpan/Atmosphere.git&lt;/a&gt;&lt;/font&gt; to set origin to Github. &lt;/li&gt;    &lt;li&gt;Run &lt;font face="Courier New"&gt;git push origin master&lt;/font&gt;. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;And there you have it, the Atmosphere repository is up and running:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/MrDustpan/Atmosphere"&gt;https://github.com/MrDustpan/Atmosphere&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7467077723377055894?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7467077723377055894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7467077723377055894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7467077723377055894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7467077723377055894'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/11/setting-up-git.html' title='Setting Up Git'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7150837462241239255</id><published>2010-11-18T18:51:00.001-08:00</published><updated>2010-11-18T18:51:30.439-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Atmosphere'/><title type='text'>Hey I’m Gonna Build My Own Blog</title><content type='html'>&lt;p&gt;I’ve decided to take on the task of writing my own blog engine.&amp;#160; &lt;a href="http://blog.wekeroad.com/2009/08/10/be-a-good-jedi-build-your-own-blog"&gt;Inspired&lt;/a&gt; as I often am by Rob Connery, and filled with a desire to work on some sort of open source project, I figured this would be a good place to start.&lt;/p&gt;  &lt;h4&gt;Why Would I Do This?&lt;/h4&gt;  &lt;p&gt;Lots of reasons.&amp;#160; Like I said, Mr. Connery told me to.&amp;#160; Plus I want to try some new things.&amp;#160; I’ve wanted to learn git/github for a while now so I think I’ll put my code out there.&amp;#160; Plus I’ve been meaning to use NHibernate in a real project (and blog about it) for a long time.&lt;/p&gt;  &lt;p&gt;I’m going to build this using “best practices” so maybe it will be helpful for others too.&amp;#160; The reason I have that in quotes is because I’ll be using the best practices I know of, which means there’s a good chance they’re not actually &lt;em&gt;the&lt;/em&gt; best.&amp;#160; But if everything goes as planned, I’ll learn a lot in the process and maybe have a cool new blog engine that I can call my own.&lt;/p&gt;  &lt;h4&gt;Features&lt;/h4&gt;  &lt;p&gt;I want to keep things simple at first, mainly so I’ll actually finish a v1.&amp;#160; In the future I’m sure I’ll add some awesome features, like the ability to make me a sandwich.&amp;#160; Here’s my list for v1:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Posts      &lt;ul&gt;       &lt;li&gt;Ability to add/edit/remove posts &lt;/li&gt;        &lt;li&gt;Ability to tag posts &lt;/li&gt;        &lt;li&gt;Ability to group posts into a series (I really like this idea) &lt;/li&gt;        &lt;li&gt;Ability to remove comments &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Comments      &lt;ul&gt;       &lt;li&gt;Ability to add comments &lt;/li&gt;        &lt;li&gt;Maybe use markdown? &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Time to Get to Work&lt;/h4&gt;  &lt;p&gt;Well it’s not much, but at this point I have a basic idea of where I want to go.&amp;#160; First steps will be to get the plumbing working, and I’ll start with getting source control setup.&amp;#160; Only thing I need to do now is come up with a name for my blog engine…how about &lt;strong&gt;Atmosphere&lt;/strong&gt;?&amp;#160; Sounds pretty awesome to me.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7150837462241239255?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7150837462241239255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7150837462241239255' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7150837462241239255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7150837462241239255'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/11/hey-im-gonna-build-my-own-blog.html' title='Hey I’m Gonna Build My Own Blog'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-5862402401695110305</id><published>2010-11-18T12:57:00.001-08:00</published><updated>2010-11-18T20:22:17.207-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Random'/><title type='text'>MSDN Gripe</title><content type='html'>&lt;p&gt;As a .NET developer, I often find myself on the &lt;a href="http://msdn.microsoft.com"&gt;MSDN website&lt;/a&gt;.&amp;#160; This is a great site with a ton of resources, not least of which is the documentation for the .NET framework.&lt;/p&gt;  &lt;p&gt;However I notice that when I Google for something I often find myself trying to avoid links to MSDN, instead looking further down the list hoping for a &lt;a href="http://stackoverflow.com"&gt;Stack Overflow&lt;/a&gt; result.&amp;#160; I think this is because it takes me a long time to drill through all of the information to find what I need.&lt;/p&gt;  &lt;p&gt;For example, I was looking for some information on LINQ to XML.&amp;#160; I have never done anything with LINQ to XML, so I was looking for a couple of samples to get me going.&amp;#160; Since I’m pretty familiar with LINQ in general, all I really need are a couple of good code samples to get me started.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Can I Have Teh Codez Plez?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Seriously, I’m a developer – I don’t actually like reading regular people words that much, show me the code.&lt;/p&gt;  &lt;p&gt;After being linked to the &lt;a href="http://msdn.microsoft.com/en-us/library/bb387098.aspx"&gt;LINQ to XML page on MSDN&lt;/a&gt; from &lt;a href="http://stackoverflow.com/questions/55828/best-practices-to-parse-xml-files"&gt;this great SO question&lt;/a&gt;, here’s what it took to see some code:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Clicked on “Samples (LINQ to XML)”. &lt;/li&gt;    &lt;li&gt;Clicked on “Introduction to LINQ to XML Sample” (since this was the c# sample). &lt;/li&gt;    &lt;li&gt;Came to a page with a bunch of words, none of them being actual code.&amp;#160; This page rambles on and on about some samples and how to install them. &lt;/li&gt;    &lt;li&gt;There is a link that looks promising, I click it.&amp;#160; Still no code.&amp;#160; Again, it’s talking about some sample library that you can download and install.&amp;#160; I’m looking for about 10 lines of code here…fail. &lt;/li&gt;    &lt;li&gt;Go to google.com. &lt;/li&gt;    &lt;li&gt;Enter “LINQ to XML sample” and search. &lt;/li&gt;    &lt;li&gt;Click on the &lt;a href="http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx"&gt;first result&lt;/a&gt;. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Don’t get me wrong, MSDN is an invaluable resource for .NET developers, just seems a little hard to find what I’m looking for at times.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-5862402401695110305?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/5862402401695110305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=5862402401695110305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/5862402401695110305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/5862402401695110305'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/11/msdn-gripe.html' title='MSDN Gripe'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-2634672280753765029</id><published>2010-06-28T07:38:00.001-07:00</published><updated>2010-06-28T07:38:37.614-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>WCF Services in ASP.NET Compatibility Mode with ASP.NET Impersonation</title><content type='html'>&lt;p&gt;Recently I was trying to setup some WCF services, hosted by IIS, to behave basically the same as ASMX services. I had a difficult time figuring out the impersonation piece - I kept getting accessed denied errors to my database because the process was running under the default ASP.NET account of the machine instead of the user my site was runnning under. I found a couple of good articles (&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/31/trusted-subsystem-wcf-and-iis-5-revisited.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx"&gt;here&lt;/a&gt;) that helped me along, but this is a more concise description of what you need to get it set up:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;IIS Setup&lt;/h3&gt;  &lt;p&gt;The site (or virtual directory) needs to be setup with Anonymous access enabled and nothing else (e.g. no Integrated Windows authentication).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Web.Config&lt;/h3&gt;  &lt;p&gt;In your servies web.config file, you need to set aspNetCompatibilityEnabled to true:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;serviceHostingEnvironment&lt;/span&gt; &lt;span style="color: #ff0000"&gt;aspNetCompatibilityEnabled&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Also, since we want to use ASP.NET impersonation (and &lt;u&gt;not&lt;/u&gt; WCF impersonation), you need to turn off WCF impersonation for all operations in the behavior configuration:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;behaviors&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;serviceBehaviors&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;behavior&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;BehaviorConfig&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;serviceAuthorization&lt;/span&gt; &lt;span style="color: #ff0000"&gt;impersonateCallerForAllOperations&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;behavior&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;serviceBehaviors&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;behaviors&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Service Classes&lt;/h3&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;And finally, each of your service classes (the actual service classes, not the interfaces) need to be marked with the appropriate AspNetCompatibilityRequirements attribute:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]&lt;/pre&gt;
&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-2634672280753765029?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/2634672280753765029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=2634672280753765029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2634672280753765029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2634672280753765029'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/06/wcf-services-in-aspnet-compatibility.html' title='WCF Services in ASP.NET Compatibility Mode with ASP.NET Impersonation'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-2168064342181728744</id><published>2010-03-14T19:36:00.001-07:00</published><updated>2010-04-22T10:43:36.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Testing Validation Attributes in ASP.NET MVC</title><content type='html'>&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: Check out the &lt;a href="http://wwwlicious.com/post/Creating-custom-DataAnnotation-tests-Part-2.aspx"&gt;AssertDataAnnotation&lt;/a&gt; class by Scott. Removes the ugliness of dealing with strings and helps you adhere to the DRY principal.&lt;/p&gt;

&lt;p&gt;One of the really cool features of MVC 2 is the integration of Data Annotation validation attributes with the model binder. You can add pre-defined validation attributes to your view models (or roll your own) and the validation is automatically performed by the magic that is MVC.&lt;/p&gt;

&lt;p&gt;Of course you’ll want to do this using TDD, so I thought I’d post a couple of sample tests that show you exactly how.&lt;/p&gt;

&lt;p&gt;Verify that an attribute exists on a model property:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[Test]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NameHasRequiredAttribute()
{
 &lt;span style="color: #008000"&gt;// Arrange&lt;/span&gt;
 var type = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(SongDetailView);
 var methodInfo = type.GetProperty(&lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;);
 &lt;span style="color: #008000"&gt;// Act&lt;/span&gt;
 var attributeExists = Attribute.IsDefined(methodInfo,
  &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(RequiredAttribute));
 &lt;span style="color: #008000"&gt;// Assert&lt;/span&gt;
 Assert.IsTrue(attributeExists);
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Verify that a property of an attribute is set correctly:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[Test]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NameHasRequiredAttribute_WithErrorMessage()
{
 &lt;span style="color: #008000"&gt;// Arrange&lt;/span&gt;
 var type = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(SongDetailView);
 var methodInfo = type.GetProperty(&lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;);
 &lt;span style="color: #008000"&gt;// Act&lt;/span&gt;
 var attribute = (RequiredAttribute)Attribute.GetCustomAttribute(
  methodInfo, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(RequiredAttribute));
 &lt;span style="color: #008000"&gt;// Assert&lt;/span&gt;
 Assert.AreEqual(&lt;span style="color: #006080"&gt;&amp;quot;Please enter a song name.&amp;quot;&lt;/span&gt;, attribute.ErrorMessage);
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The model I’m forced to create:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SongDetailView
{
 [Required(ErrorMessage=&lt;span style="color: #006080"&gt;&amp;quot;Please enter a song name.&amp;quot;&lt;/span&gt;)]
 &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }
}&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-2168064342181728744?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/2168064342181728744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=2168064342181728744' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2168064342181728744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2168064342181728744'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/03/testing-validation-attributes-in-aspnet.html' title='Testing Validation Attributes in ASP.NET MVC'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-893213667585541179</id><published>2010-01-13T11:14:00.001-08:00</published><updated>2010-01-13T11:15:08.677-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>TDD Code Snippet for Visual Studio</title><content type='html'>&lt;p&gt;Here’s a little code snippet I wrote for Visual Studio.&amp;#160; It creates the shell of a Test Driven Development test (or any unit test, I suppose).&amp;#160; Here’s how to install it:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Open up your snippets folder.&amp;#160; It will most likely be somewhere like this:      &lt;br /&gt;&lt;font face="Courier New"&gt;C:\Documents and Settings\userName\My Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets       &lt;br /&gt;&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Create a new text file and rename it to “tdd.snippet”.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Open the file, and paste this inside:      &lt;br /&gt;      &lt;br /&gt;      &lt;div&gt;       &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;         &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #800000"&gt;xml&lt;/span&gt; &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;encoding&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;utf-8&amp;quot;&lt;/span&gt; ?&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;CodeSnippets&lt;/span&gt;  &lt;span style="color: #ff0000"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;CodeSnippet&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Format&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1.0.0&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Header&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Title&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;tdd&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Title&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Shortcut&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;tdd&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Shortcut&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Description&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Code snippet for creating TDD test shell&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Description&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Author&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Dustin Brown&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Author&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;SnippetTypes&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;SnippetType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Expansion&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;SnippetType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;SnippetTypes&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Header&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Snippet&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Code&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Language&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;csharp&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[[TestMethod]&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     public void If_When_Then()&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         // Arrange&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;       &lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         // Act&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;       &lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         // Assert&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     }]]&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Code&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Snippet&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;CodeSnippet&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;CodeSnippets&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;

      &lt;br /&gt;&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;Save the file and fire up Visual Studio.&amp;#160; You should see the snippet in your Code Snippets Manager (Ctrl+K, Ctrl+B). 
    &lt;br /&gt;

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Now, when you’re going to write a test, just type “tdd” and hit Tab twice.&amp;#160; You’ll see something like this: 
    &lt;br /&gt;

    &lt;br /&gt;

    &lt;div&gt;
      &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; [TestMethod]&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; If_When_Then()&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Arrange&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Act&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Assert&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Obviously this works well for me – I’m using MS Test and I like to name my tests using an “If_When_Then” pattern.&amp;#160; But if you’re using another testing framework, such as NUnit, or you like you use a different naming convention, just modify the snippet.&lt;/p&gt;

&lt;p&gt;Also you could get fancy and add place holders in the method name so you could tab through and enter each part of the method name.&lt;/p&gt;

&lt;p&gt;Cheers! 
  &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-893213667585541179?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/893213667585541179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=893213667585541179' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/893213667585541179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/893213667585541179'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2010/01/tdd-code-snippet-for-visual-studio.html' title='TDD Code Snippet for Visual Studio'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7568321187613336758</id><published>2009-11-19T15:50:00.001-08:00</published><updated>2009-11-19T15:51:03.238-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDC 09'/><title type='text'>PDC 09 : Days 2 &amp; 3</title><content type='html'>&lt;p&gt;The past couple days have been pretty crazy.  I didn’t have a chance to blog last night because I was too beat after Geekfest!&lt;/p&gt;&lt;p&gt;Here is some random stuff from the past 2 days:&lt;/p&gt;&lt;h4&gt;Keynote day 2:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/"&gt;The Gu&lt;/a&gt; gave a great keynote and talked about Silverlight pretty much the entire time.  I’m really getting the feeling that this is a big piece the future of web development for Microsoft. &lt;/li&gt;&lt;li&gt;There was a lot of talk about Windows 7 and how awesome it is, and how they really want us to create some butt kicking apps to make it better. &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/a&gt; gave a little demo of creating a business app with Silverlight, that was cool. &lt;/li&gt;&lt;li&gt;They made the big announcement that all PDC attendees would receive a free &lt;a href="http://windowsteamblog.com/blogs/windowsexperience/archive/2009/11/18/sneak-peak-at-the-acer-aspire-1420p.aspx"&gt;tablet PC&lt;/a&gt;!  I’m actually writing this post on mine now.  Super sweet! &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Model-View-Ninja!&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;After the keynote I went to Hanselman’s session on asp.net mvc 2.  It was titled something like “Super awesome ninjas on fire and mvc 2” or something.  It was really good, probably my favorite session at the conference.  He was super funny and informative, as always. &lt;/li&gt;&lt;li&gt;I attended another session by &lt;a href="http://stephenwalther.com/blog/default.aspx"&gt;Stephen Walther&lt;/a&gt; on MVC 2 where he covered all of the new stuff.  A lot of cool enhancements that I really like. &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Geekfest&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;After the day was over they had Geekfest!  A big party with games, beer, food and pumping music.  It was fun, but only 2 hours long :( &lt;/li&gt;&lt;li&gt;My coworker and I ended the evening by playing a little Halo on the 360 machines they had setup. &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Takeaways&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Here’s a list of stuff that I heard a lot about, and I want to learn much more: &lt;ul&gt;&lt;li&gt;Azure &lt;/li&gt;&lt;li&gt;Silverlight &lt;/li&gt;&lt;li&gt;RIA Services &lt;/li&gt;&lt;li&gt;MVC 2 &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;PDC this year was a blast.  Tons of content, more than I could take in.  I’ll be hitting the PDC site to download sessions that I missed and I’ll be digging into some of the labs I didn’t have a chance to get through.  It was a crazy 3 days, but loads of fun! &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7568321187613336758?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7568321187613336758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7568321187613336758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7568321187613336758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7568321187613336758'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/11/pdc-09-days-2-3.html' title='PDC 09 : Days 2 &amp;amp; 3'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-142566364398655436</id><published>2009-11-17T22:31:00.001-08:00</published><updated>2009-11-17T22:31:41.651-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDC 09'/><title type='text'>PDC 09 : Day 1</title><content type='html'>&lt;p&gt;Wow, I’m beat.&amp;#160; Just got back to the hotel after a full day at the convention.&amp;#160; Here are some highlights:&lt;/p&gt;  &lt;h4&gt;It’s All About the Cloud&lt;/h4&gt;  &lt;p&gt;This morning’s keynote focused almost entirely on the Windows Azure stack.&amp;#160; It seems clear that Microsoft is very serious about Azure and it sounds like it will be a big part of their technology in the future.&amp;#160; Ray Ozzie talked about the “3 Screens &amp;amp; a Cloud” a lot.&amp;#160; Basically the idea that your mobile device, your pc, and your TV should all seamlessly work together using apps hosted in the cloud.&lt;/p&gt;  &lt;p&gt;There was also a lot of emphasis on Silverlight.&amp;#160; Up to this point my exposure to Silverlight has been pretty limited, but I think I’d like to explore that more.&amp;#160; I’m especially intrigued by the idea of Silverlight + ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;After the keynote I attended the “Lap Around Azure” session.&amp;#160; It was pretty informative and had a couple of demos (which I always like – show me the code!).&amp;#160; I think I’m really going to need to dig into this myself.&amp;#160; If only there were hands on labs here…&lt;/p&gt;  &lt;h4&gt;Hand on Labs&lt;/h4&gt;  &lt;p&gt;So after the Azure session, it was lunch time (awesome food btw).&amp;#160; After I scarfed down my food I figured I would hit the Azure labs because I wanted to get some real experience and learn something.&amp;#160; When I got to the labs there was a line of about 200 people waiting to get into the Azure labs.&amp;#160; Oh yeah, there was also some flip camcorder giveaway for people that would attend an Azure session and then do a lab.&lt;/p&gt;  &lt;p&gt;So I abandoned that idea and decided to check out the web platform labs.&amp;#160; On my way there I strolled by the Channel 9 live broadcast and it was &lt;a href="http://hanselman.com/"&gt;Scott Hanselman&lt;/a&gt; interviewing the guy who runs failblog.org!!&amp;#160; I sat and watch that for a few minutes, Scott was super funny as usual.&amp;#160; I was a little star struck – Hanselman is totally my hero…well one of my heroes anyway.&lt;/p&gt;  &lt;p&gt;I then hit the ASP.NET labs and started one that was ASP MVC 2, Ajax and Entity Framework.&amp;#160; The lab was awesome but I didn’t finish it.&amp;#160; The VM I was working on was really sluggish and there was a &lt;u&gt;lot&lt;/u&gt; of code to write!&lt;/p&gt;  &lt;h4&gt;BDD &amp;amp; TDD&lt;/h4&gt;  &lt;p&gt;After that I went to a Birds of a Feather session on BDD (Behavior Driven Design) and TDD (Test Driven Development).&amp;#160; These BOF sessions are meant to be a discussion where the attendees are involved.&amp;#160; This is near and dear to my heart because I’m a TDD fan boy.&lt;/p&gt;  &lt;p&gt;There were a lot of people there that didn’t really know what TDD was, and even more (myself included) that didn’t know much about BDD.&amp;#160; It was a very lively and entertaining discussion.&lt;/p&gt;  &lt;h4&gt;Partner Expo&lt;/h4&gt;  &lt;p&gt;After that was the partner expo.&amp;#160; Lots of good food and drink, saw Scott Hanselman get out-coded by a dude with Rock Band guitar (I know it was the crappy keyboard!), and talked to a bunch of cool vendors.&lt;/p&gt;  &lt;p&gt;I signed up for a trial with &lt;a href="http://my.safaribooksonline.com/"&gt;Safari Books Online&lt;/a&gt; which I’m super pumped about.&amp;#160; They even gave me a free book which was sweet.&amp;#160; Also got a couple of t-shirts and other swag, and had a really good time.&lt;/p&gt;  &lt;p&gt;Can’t wait for tomorrow!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-142566364398655436?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/142566364398655436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=142566364398655436' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/142566364398655436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/142566364398655436'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/11/pdc-09-day-1.html' title='PDC 09 : Day 1'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7573560851745708977</id><published>2009-10-19T10:17:00.000-07:00</published><updated>2009-10-19T10:19:40.293-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL CDC'/><title type='text'>SQL Change Data Capture __$operation Values</title><content type='html'>&lt;span class="Apple-style-span"   style="  border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family:Verdana;font-size:12px;"&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; "&gt;In case you want to know what the value of the __$operation field means in a SQL CDC table, here ya go:&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; "&gt;1 = delete&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; "&gt;2 = insert&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; "&gt;3 = update (before the update)&lt;/p&gt;&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; "&gt;4 = update (after the update)&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7573560851745708977?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7573560851745708977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7573560851745708977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7573560851745708977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7573560851745708977'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/10/sql-change-data-capture-operation.html' title='SQL Change Data Capture __$operation Values'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-6631658349350833192</id><published>2009-10-01T19:45:00.001-07:00</published><updated>2009-10-01T19:45:41.558-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq to SQL'/><title type='text'>Linq to SQL – Roll Your Own Domain Model</title><content type='html'>&lt;p&gt;When using Linq to SQL in Visual Studio, there is a really nifty designer interface.&amp;#160; It allows you to drag tables (and views, stored procedures, etc.) from a database onto the designer surface.&amp;#160; Behind the scenes a domain model class is created.&amp;#160; Using the DataContext, you can persist data to, and retrieve data from, the database using these strongly typed domain objects.&lt;/p&gt;  &lt;p&gt;This offers several advantages:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Easy to use – just drag your tables onto the designer. &lt;/li&gt;    &lt;li&gt;The DataContext handles many “infrastructure” tasks for you:&amp;#160; transactions, concurrency checking, parameterized SQL, etc. &lt;/li&gt;    &lt;li&gt;Strongly typed objects that are partial classes - they can be extended to add your business logic. &lt;/li&gt;    &lt;li&gt;A nice visual representation of your domain in the designer. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;However, there are a few big disadvantages:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Your domain models are tightly coupled to your ORM technology (Linq to SQL). &lt;/li&gt;    &lt;li&gt;Any other layer of your application that wants to have access to your domain models would have to reference the project that contains your data access. &lt;/li&gt;    &lt;li&gt;Unless you plan to modify (and maintain) the models that are auto-generated, your database schema has to mirror your domain model. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There is an approach that we can take that will alleviate most of the disadvantages while still offering us the benefits.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;I’ll Create My Own Models, Thank You Very Much&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;What we can do is create our own models and map them (yes, using xml) to the correct database table.&amp;#160; This removes the mapping from our domain models and allows us to put them in a totally different assembly if we want.&lt;/p&gt;  &lt;p&gt;Let’s pretend like we know how to do &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;Domain Driven Design&lt;/a&gt;, and design a super useful application about dogs.&amp;#160; We’ll say we’ve come up with the following nouns and verbs about a dog:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Nouns&lt;/em&gt;     &lt;br /&gt;- Breed     &lt;br /&gt;- Name     &lt;br /&gt;- Weight&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Verbs&lt;/em&gt;     &lt;br /&gt;- Bark&lt;/p&gt;  &lt;p&gt;Like I said, super useful.&amp;#160; So here’s what that might look like translated into code:&lt;/p&gt;  &lt;p&gt;The Model:&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Core.Models&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Dog&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Id { get; set; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Breed { get; set; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Weight { get; set; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Bark()&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// Do some barking&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;the Mapping XML:&lt;/p&gt;

&lt;div&gt;
  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #800000"&gt;xml&lt;/span&gt; &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;encoding&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;utf-8&amp;quot;&lt;/span&gt; ?&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Database&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;DogDb&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/linqtosql/mapping/2007&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Table&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Dog&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Type&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Core.Models.Dog&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Column&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Member&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;                 &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Id&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;                 &lt;span style="color: #ff0000"&gt;AutoSync&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;OnInsert&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;                 &lt;span style="color: #ff0000"&gt;IsPrimaryKey&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;                 &lt;span style="color: #ff0000"&gt;IsDbGenerated&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;                 &lt;span style="color: #ff0000"&gt;DbType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Int NOT NULL IDENTITY&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Column&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Member&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Breed&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Breed&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;DbType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;VarChar(50) NOT NULL&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Column&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Member&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;DbType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;VarChar(50) NOT NULL&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Column&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Member&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Weight&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Weight&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;DbType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Int NOT NULL&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Database&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;and the Repository:&lt;/p&gt;

&lt;div&gt;
  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Infrastructure&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DogRepository : IDogRepository&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; DataContext _db;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DogRepository()&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             XmlMappingSource map = XmlMappingSource.FromXml(File.ReadAllText(&lt;span style="color: #006080"&gt;&amp;quot;DogMap.xml&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             _db = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DataContext(&lt;span style="color: #006080"&gt;&amp;quot;ConnectionString&amp;quot;&lt;/span&gt;, map);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Dog Fetch(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; dogId)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _db.GetTable&amp;lt;Dog&amp;gt;().SingleOrDefault(x =&amp;gt; x.Id == dogId);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Add(Dog dog)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             _db.GetTable&amp;lt;Dog&amp;gt;().InsertOnSubmit(dog);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Delete(Dog dog)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             _db.GetTable&amp;lt;Dog&amp;gt;().DeleteOnSubmit(dog);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SubmitChanges()&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             _db.SubmitChanges();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Pretty simple and elegant.&amp;#160; Not perfect though.&amp;#160; Yes XML sucks, and yes the repository is still tightly coupled to Linq to SQL, but at least with this approach our model isn’t cluttered with ORM specific attributes.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-6631658349350833192?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/6631658349350833192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=6631658349350833192' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6631658349350833192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6631658349350833192'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/10/linq-to-sql-roll-your-own-domain-model.html' title='Linq to SQL – Roll Your Own Domain Model'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-6637222339270167847</id><published>2009-07-23T13:54:00.003-07:00</published><updated>2010-11-16T12:18:51.084-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 4: Conclusion</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 4: Conclusion&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Well I hope you’ve enjoyed this series.&amp;#160; Again, I wasn’t aiming to answer every question around TDD, as I still have many myself.&amp;#160; But rather I wanted to share my experiences in hopes that it might help someone else.&lt;/p&gt;  &lt;p&gt;Also, I would really love some feedback on all this, so if you have questions or comments please let me know!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-6637222339270167847?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/6637222339270167847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=6637222339270167847' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6637222339270167847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6637222339270167847'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-4-conclusion.html' title='TDD Part 4: Conclusion'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-1903024430355823213</id><published>2009-07-23T13:54:00.001-07:00</published><updated>2010-11-16T12:18:22.368-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 3, Key #3: Using Fakes and Dependency Injection</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Thumbs up" border="0" alt="Thumbs up" align="left" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjODkC287I/AAAAAAAAAEM/astVmPwRBkI/thumbs_up6.png?imgmax=800" width="244" height="223" /&gt; As &lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;mentioned earlier&lt;/a&gt;, we need to be able to use Dependency Injection so we aren’t testing more than one thing.&amp;#160; And if we don’t want to test more than one thing, that means we’ll have to “inject” same fake objects.&lt;/p&gt;  &lt;p&gt;Using Fakes (or Mocks as many people refer to them) was one of those things that took me a while to understand.&lt;/p&gt;  &lt;p&gt;When I first started TDD, I would create my own “mock” classes, like a mock repository that would return real data.&amp;#160;&amp;#160; In the mock class, I would essentially build up an in-memory database that I could then query and return data from.&amp;#160; Needless to say, that was a huge pain and was not maintainable.&lt;/p&gt;  &lt;p&gt;Then I started reading about mocking frameworks.&amp;#160; But still I didn’t get it.&amp;#160; “They don’t do anything, what’s the point?”&amp;#160; But that &lt;em&gt;is&lt;/em&gt; the point, we don’t want them to do anything.&amp;#160; They are just there to either allow our code to run, or so we can verify that they were utilized correctly.&lt;/p&gt;  &lt;p&gt;Here is a sample test checks to see if our PrintInvoice() method calls the repository like it should (using Moq as the mocking framework):&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Test" border="0" alt="Test" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjOD3LSljI/AAAAAAAAAEQ/DT4ZeQtn80g/code75.png?imgmax=800" width="736" height="421" /&gt; &lt;/p&gt;  &lt;p&gt;This might seem a little crazy so let’s break it down.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;First of all, notice the Arrange, Act and Assert sections.&amp;#160; I like to put this in each of my tests to remind me that my test has 3 parts.&amp;#160; First, setup the test scenario.&amp;#160; Then perform some action – this is what we’re actually testing.&amp;#160; Finally, verify that what we expected to happen actually happened. &lt;/li&gt;    &lt;li&gt;In the Arrange section, I’m setting up four Fake objects.&amp;#160; These will be passed into the InvoicePrinter constructor so we can perform our tests.&amp;#160; Keep in mind, these objects are fake and don’t really do anything, they’re just there so we can run our test and verify that it worked. &lt;/li&gt;    &lt;li&gt;The Assert line might be a bit confusing – it was for me at first.&amp;#160; But really it’s saying “verify that my mock repository object had it’s FetchOrder() method called exactly once, and that the value passed into it was 1234.” &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Fakes, Mocks, &amp;amp; Stubs?!?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;As Martin Fowler put it&lt;/a&gt;, mocks aren’t stubs!&amp;#160; So what are mocks, stubs, and fakes – and what difference does it make?&amp;#160; Here’s a short explanation of each:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Fake == a generic term for Mocks &amp;amp; Stubs &lt;/li&gt;    &lt;li&gt;Mock == a Fake that is used to verify something &lt;/li&gt;    &lt;li&gt;Stub == a Fake that is just a place holder so your code can run &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So in the example above, the repository object was a Mock.&amp;#160; That’s because we verified that some certain behavior on that object was invoked.&amp;#160; The other Fakes in that method are all Stubs – they’re just there so our test can run.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;IoC Containers&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let’s say we have this class:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SalesTaxCalculator" border="0" alt="SalesTaxCalculator" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjOEF1oDPI/AAAAAAAAAEU/fhuFPzcMHO4/code85.png?imgmax=800" width="623" height="302" /&gt; &lt;/p&gt;  &lt;p&gt;As you can see we are using Dependency Injection for our ILogger.&amp;#160; This allows us to test just our SalesTaxCalculator class without worrying about the concrete implementation of ILogger.&lt;/p&gt;  &lt;p&gt;But what about our “real” code?&amp;#160; At some point we need to create a concrete implementation of the ILogger interface and get it into our class, right?&lt;/p&gt;  &lt;p&gt;There are a couple of ways we could do this.&amp;#160; We could have another constructor that doesn’t take any arguments and defaults _logger to our real Logger class.&amp;#160; But that’s a little smelly – we are technically still coupled to that Logger class in some way.&lt;/p&gt;  &lt;p&gt;Another way to do it is to use an Inversion of Control Container (IoC Container).&amp;#160; These are utilities that allow you configure what the default implementation of a given interface is.&amp;#160; Then, when that interface is required, the IoC container will give you an instance of the default.&lt;/p&gt;  &lt;p&gt;For example, here is what a Castle Windsor configuration might look like for our ILogger interface:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Castle Configuration" border="0" alt="Castle Configuration" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjOEWAgQVI/AAAAAAAAAEY/yoIuw0TFl1A/config5.png?imgmax=800" width="401" height="99" /&gt; &lt;/p&gt;  &lt;p&gt;This tells Castle:&amp;#160; “Anytime I’m looking for an ILogger, give me a Logger.&amp;#160; By the way, ILogger and Logger are both in MyApp.dll under the MyApp namespace.”&lt;/p&gt;  &lt;p&gt;So if we are configured to use IoC, we don’t have to change our SalesTaxCalculator class at all.&amp;#160; The IoC container will just give us the correct concrete class any time we need one.&lt;/p&gt;  &lt;p&gt;Simone Busoli has an &lt;a href="http://dotnetslackers.com/articles/designpatterns/InversionOfControlAndDependencyInjectionWithCastleWindsorContainerPart1.aspx"&gt;awesome four part article&lt;/a&gt; on using Castle Windsor.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-1903024430355823213?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/1903024430355823213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=1903024430355823213' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1903024430355823213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1903024430355823213'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-3-key-3-using-fakes-and.html' title='TDD Part 3, Key #3: Using Fakes and Dependency Injection'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_Ibq67iO0TPU/SmjODkC287I/AAAAAAAAAEM/astVmPwRBkI/s72-c/thumbs_up6.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-8397281310233586627</id><published>2009-07-23T13:53:00.001-07:00</published><updated>2010-11-16T12:17:55.427-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 3, Key #2: Write Good Tests</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 3, Key #2: Write Good Tests&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="SecondKey" border="0" alt="SecondKey" align="right" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNwmmnUqI/AAAAAAAAAEI/-lhevf9cGlo/SecondKey7.jpg?imgmax=800" width="164" height="244" /&gt;&lt;/p&gt;  &lt;p&gt;This is an obvious one, but what does it mean to write “good” tests?&amp;#160; There is a great &lt;a href="http://hanselminutes.com/default.aspx?showID=187"&gt;Hanselminutes podcast&lt;/a&gt; with &lt;a href="http://weblogs.asp.net/rosherove/"&gt;Roy Osherove&lt;/a&gt; that gives you an idea of what makes good tests.&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Your Tests Should Be Readable&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;Your tests are code too, and just like all of your other code you want it to be nice and readable.&amp;#160; This means naming your classes, functions and variables with meaning!     &lt;br /&gt;    &lt;br /&gt;InvoicePrinterTests is a good name for a class that tests the InvoicePrinter class.&amp;#160; TestClass1 is not.     &lt;br /&gt;    &lt;br /&gt;PrintInvoice_Calls_Repository_FetchOrder() is a good name for a test that verifies that the OrderRepository.FetchOrder() method is called when we call PrintInvoice().&amp;#160; Test1() is not.     &lt;br /&gt;    &lt;br /&gt;I like to name my test functions so they read like English, and if you were to replace the underscores with spaces, you’d have a pretty understandable statement (“PrintInvoice calls repository FetchOrder”).&amp;#160; If you don’t like underscores, that’s fine – just choose a convention that helps you describe &lt;em&gt;exactly&lt;/em&gt; what the function is testing.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Your Tests Should Be Maintainable&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;Just like with “regular” code, we want our tests to be maintainable.&amp;#160; This means your test functions should probably be no more than 10-15 lines in length.     &lt;br /&gt;    &lt;br /&gt;And another thing I’ve discovered:&amp;#160; if you run into a situation where you’re finding it hard to test something, or your test is just getting big and complicated – you almost certainly need to refactor something.&amp;#160; I’ve run into this many times and &lt;u&gt;every&lt;/u&gt; time I found that it was because the code I was trying to test was too complicated and needed to be split up and tested separately.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Your Tests Should Test Only One Thing&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;Each test function should test one, and &lt;em&gt;only&lt;/em&gt; one, thing.&amp;#160; A good check (although this isn’t always true) is to see whether you have more than one Assert statement.&amp;#160; If so, there’s a good chance that you are testing more than one thing.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Your Tests Should Be Trustworthy&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;In order for tests to have long lasting value, you have to trust them.&amp;#160; If you’re not confident in your tests, then you can’t be confident in the results they produce.&amp;#160; If, on the other hand, you are totally confident in your tests, when they fail you can be sure that there is a bug in your code that needs to get squashed.     &lt;br /&gt;    &lt;br /&gt;How do you make “trustworthy” tests?&amp;#160; If you follow the 3 guidelines above, you’ll be well upon your way. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-8397281310233586627?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/8397281310233586627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=8397281310233586627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/8397281310233586627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/8397281310233586627'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-3-key-2-write-good-tests.html' title='TDD Part 3, Key #2: Write Good Tests'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNwmmnUqI/AAAAAAAAAEI/-lhevf9cGlo/s72-c/SecondKey7.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-3884338705690214258</id><published>2009-07-23T13:52:00.001-07:00</published><updated>2010-11-16T12:17:28.882-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 3, Key #1: Write Testable Code</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 3, Key #1: Write Testable Code&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="I&amp;#39;m #1" border="0" alt="I&amp;#39;m #1" align="left" src="http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNpj9NvBI/AAAAAAAAAD8/YdV9PyIWgUE/ImNumberOne14.jpg?imgmax=800" width="354" height="354" /&gt; &lt;/p&gt;  &lt;p&gt;So if you want to test your code, you need to write that code can be tested.&amp;#160; Wow, astounding.&amp;#160; That’s like saying if you want to score a touchdown you need to get the football in the end zone.&lt;/p&gt;  &lt;p&gt;Well, put another way – you need to structure your code in such a way that makes it easier to test.&amp;#160; So what does that mean?&amp;#160; A few things:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;u&gt;Separation of Concerns&lt;/u&gt;       &lt;br /&gt;      &lt;br /&gt;In order to have an effective unit test, you need to be testing only &lt;em&gt;one&lt;/em&gt; thing.&amp;#160; That means your code needs to be written so each of the “concerns” are isolated into small, testable chunks.&amp;#160; Which brings us to our next point:       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;u&gt;Single Responsibility&lt;/u&gt;       &lt;br /&gt;      &lt;br /&gt;This is really an extension of the previous point, but to achieve separation of concerns a good approach is the &lt;a href="http://www.objectmentor.com/resources/articles/srp.pdf"&gt;Single Responsibility Principle&lt;/a&gt; (pdf).&amp;#160; This states that a class should have one, and only one, reason to change.&amp;#160; In other words a class should do only one thing (and do it well!)&amp;#160; This means that your ShippingCalculator class shouldn’t calculate shipping &lt;u&gt;and&lt;/u&gt; write logging information to a text file.&amp;#160; It should call out to a separate Logger class to do that.       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;u&gt;Inversion of Control&lt;/u&gt;       &lt;br /&gt;      &lt;br /&gt;Ok, so I’ve separated my concerns into single responsibilities, that’s cool.&amp;#160; But now if I want to test my CalculateShipping() method, it will end up calling my Logger class too.&amp;#160; Doesn’t that mean I’m really testing more than one thing, which is not what I want to do?&amp;#160; Exactly.       &lt;br /&gt;      &lt;br /&gt;So, instead of calling our real Logger class, it would be nice if (during our testing) we called a “fake” class that didn’t do anything.&amp;#160; Enter &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control&lt;/a&gt; (IoC) and “Fakes”.       &lt;br /&gt;      &lt;br /&gt;IoC means that instead of a class being responsible for creating the other classes it depends upon, these are provided to it (thus “inverting” the control).&amp;#160; This allows us to inject our dependencies into our classes which will allow us to use a “fake” logger when our tests run, and the “real” logger in the production code. (Another common term for IoC is Dependency Injection.) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Let’s take a look at a couple samples.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="1"&gt;Class 1:&amp;#160; Not very “testable”:&lt;/font&gt;&lt;/strong&gt;&amp;#160; &lt;br /&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Not very testable" border="0" alt="Not very testable" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNpyRuRcI/AAAAAAAAAEA/apWTT51t8Pg/code55.png?imgmax=800" width="765" height="414" /&gt; &lt;/p&gt;  &lt;p&gt;Here are the problems that I see with this class:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Concerns are not separated.&amp;#160; This method is calculating sales tax, logging to a file, and printing and invoice.&amp;#160; It’s hard to test only one thing when our method is doing three things. &lt;/li&gt;    &lt;li&gt;This function is performing disk IO and, presumably, connecting to a real database through the OrderRepository class.&amp;#160; This can cause our tests to be brittle and slow.&amp;#160; Not good! &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Let’s take a look at a more testable version:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;strong&gt;&lt;font size="1"&gt;Class 2:&amp;#160; Now that’s what I call testable!&lt;/font&gt;&lt;/strong&gt;&amp;#160;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Testable!" border="0" alt="Testable!" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNqAsIfUI/AAAAAAAAAEE/1djkih9cOik/code65.png?imgmax=800" width="762" height="581" /&gt; &lt;/p&gt;  &lt;p&gt;What’s so great about this class?&amp;#160; Well, none of the problems identified above are there anymore.&amp;#160; We can write tests that will only test this specific function of this class.&lt;/p&gt;  &lt;p&gt;Now you might be noticing that this function doesn’t really do anything.&amp;#160; That’s right!&amp;#160; It’s really more of an aggregator that combines the functionality of other classes to perform some operation.&lt;/p&gt;  &lt;p&gt;So how would you test this method?&amp;#160; Well I would probably have 4 tests:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Verify that the FetchOrder() method on my IOrderRepository gets called. &lt;/li&gt;    &lt;li&gt;Verify that the Calculate() method on my ISalesTaxCalculator gets called. &lt;/li&gt;    &lt;li&gt;Verify that the Log() method on my ILogger gets called. &lt;/li&gt;    &lt;li&gt;Verify that the Print() method on my IPrinter gets called. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That’s it.&amp;#160; We’re testing what this function does, which is call other functions.&amp;#160; So, assuming that we have other tests that will test each of those other functions, this PrintInvoice() method is totally covered by unit tests.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-3884338705690214258?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/3884338705690214258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=3884338705690214258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3884338705690214258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3884338705690214258'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-3-key-1-write-testable-code.html' title='TDD Part 3, Key #1: Write Testable Code'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNpj9NvBI/AAAAAAAAAD8/YdV9PyIWgUE/s72-c/ImNumberOne14.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-1437794728771687593</id><published>2009-07-23T13:51:00.003-07:00</published><updated>2010-11-16T12:17:01.005-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 3: Keys to Effective TDD</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 3: Keys to Effective TDD&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNa0YKm0I/AAAAAAAAAD0/0GjjFDP9fwg/s1600-h/keys4.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Don&amp;#39;t chew on these" border="0" alt="Don&amp;#39;t chew on these" align="left" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNbMMteMI/AAAAAAAAAD4/r7yhWuRQbR4/keys_thumb2.jpg?imgmax=800" width="228" height="279" /&gt;&lt;/a&gt; When I first started using TDD, it was a struggle.&amp;#160; My tests seemed as complicated as the actual classes I was trying to write, and I didn’t really feel like I was getting a lot of benefit from the tests.&lt;/p&gt;  &lt;p&gt;When I would change some code that would cause a test to fail, I didn’t really have confidence in the test.&amp;#160; So instead of fixing the code, or refactoring the test to meet the new functionality, I would sometimes end up just commenting out the test itself.&lt;/p&gt;  &lt;p&gt;Not very useful.&lt;/p&gt;  &lt;p&gt;Not to mention maintaining all of my “mock” classes, such as repositories, that would contain enough data and functionality to make my tests useful.&amp;#160; It was a headache and found myself nearly giving up on the practice.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;But over time, I realized a few key items that helped make TDD more effective.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Write Testable Code &lt;/li&gt;    &lt;li&gt;Write Good Tests &lt;/li&gt;    &lt;li&gt;Use Fakes and Dependency Injection &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’ll expand on these three points in my next three posts.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-1437794728771687593?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/1437794728771687593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=1437794728771687593' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1437794728771687593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1437794728771687593'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-3-keys-to-effective-tdd.html' title='TDD Part 3: Keys to Effective TDD'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNbMMteMI/AAAAAAAAAD4/r7yhWuRQbR4/s72-c/keys_thumb2.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-3350701702094883122</id><published>2009-07-23T13:51:00.001-07:00</published><updated>2010-11-16T12:16:09.322-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 2: Write My Tests First?</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 2: Write My Tests First?&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNMk4qRAI/AAAAAAAAADQ/ZS3sSR4uRoE/s1600-h/confusedmonkey3.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="confused-monkey" border="0" alt="confused-monkey" align="left" src="http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNM4FML9I/AAAAAAAAADU/832yprTf5-0/confusedmonkey_thumb1.jpg?imgmax=800" width="244" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When I first read about TDD (many years ago), one of the first things I saw was: write your tests first.&lt;/p&gt;  &lt;p&gt;“What?&lt;/p&gt;  &lt;p&gt;This is stupid, I’m gonna go get a sandwich.”&lt;/p&gt;  &lt;p&gt;That idea didn’t make sense to me, and I think that’s probably the reaction most developers who don’t use TDD would have.&lt;/p&gt;  &lt;p&gt;How can you test something that doesn’t exist?&amp;#160; Well, you can’t.&amp;#160; But the idea, as mentioned in the previous post, is that this isn’t just about testing.&amp;#160; It’s really about design.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“Ok, so I write &lt;em&gt;all&lt;/em&gt; my tests and then write my code?&amp;#160; How am I supposed to do that.&amp;#160; I still don’t get it.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That was a big misunderstanding of mine.&amp;#160; You don’t write all of your tests up front, you write them one at a time and then write the code to satisfy those tests – one at a time.&amp;#160; You start small and your tests force you to slowly create your classes and functions.&amp;#160; Eventually, where there was a blank screen, now you have a bunch of functional code that is covered by tests.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The Red, Green, Refactor Show&lt;a href="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNMwbNGRI/AAAAAAAAADY/mHSBg0k-b_k/s1600-h/the_red_green_show3.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="the_red_green_show" border="0" alt="the_red_green_show" align="right" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjNNAzpRJI/AAAAAAAAADc/TV_x--Z9_1g/the_red_green_show_thumb1.jpg?imgmax=800" width="178" height="244" /&gt;&lt;/a&gt; &lt;/b&gt;    &lt;br /&gt;The “test-first” approach basically has 3 steps:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#ff0000"&gt;&lt;u&gt;Red&lt;/u&gt;&lt;/font&gt; – Write a test and make sure it fails.&amp;#160; It’s called the “Red” step because most unit testing tools will display a red failure message.&amp;#160; Failure is good at this point.&amp;#160; We love failure. &lt;/li&gt;    &lt;li&gt;&lt;font color="#008000"&gt;&lt;u&gt;Green&lt;/u&gt;&lt;/font&gt; – Write the minimum amount of code to make your test pass.&amp;#160; And yes, the unit testing tools will display a nice lovely green message.&amp;#160; Ah, green…success, peacefulness. &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Refactor&lt;/u&gt; – You have some code that passes a test, way to go.&amp;#160; But guess what?&amp;#160; That code sucks.&amp;#160; Refactor that code so it is nice and pretty.&amp;#160; This step doesn’t have to occur after each test is written.&amp;#160; You might want to wait until you have a few methods, maybe even an entire module, done before you refactor it. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Where Do I Start?&lt;/b&gt;     &lt;br /&gt;Let’s see this in action with an example.&amp;#160; Let’s say the first thing we want to do is write this “calculate shipping module”.&amp;#160; We don’t know if it will be 1 method, or 10, or 100.&amp;#160; But the tests will guide us.&lt;/p&gt;  &lt;p&gt;All right, what’s the first requirement?&lt;/p&gt;  &lt;blockquote&gt;   &lt;table border="1" cellspacing="0" bordercolor="#cccccc" cellpadding="3" width="258" bgcolor="#eeeeee"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="256"&gt;           &lt;ol&gt;             &lt;li&gt;Shipping = Order quantity * 3 &lt;/li&gt;           &lt;/ol&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;What do we know?&amp;#160; Well from that requirement I’d say we need a method that accepts order quantity as a parameter and returns that number multiplied by 3.&amp;#160; Pretty easy, so let’s write our first test!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Our first test!" border="0" alt="Our first test!" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNNf7r72I/AAAAAAAAADg/37l_zzxfBec/code111.png?imgmax=800" width="507" height="230" /&gt;     &lt;br /&gt;    &lt;br /&gt;So with these 3 small lines of code, we are essentially creating the following truths:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;We have a class called ShippingCalculator. &lt;/li&gt;    &lt;li&gt;This class has a method Calculate(), that accepts an integer parameter. &lt;/li&gt;    &lt;li&gt;The Calculate() method will return the input parameter multiplied by 3. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now that’s pretty cool!&amp;#160; Of course, these aren’t exactly truths yet since this code won’t even compile (as evidenced by the red squiggly line!)&amp;#160; But that’s the way we want it, we are in the &lt;strong&gt;&lt;font color="#ff0000"&gt;red&lt;/font&gt;&lt;/strong&gt; portion of red/green/refactor.&amp;#160; And the first “red” test is the compile failure.&amp;#160; So, let’s write enough code to make it compile:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ShippingCalculator class" border="0" alt="ShippingCalculator class" src="http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNNiFVEvI/AAAAAAAAADk/CtEMZN1wDi8/code26.png?imgmax=800" width="466" height="147" /&gt; &lt;/p&gt;  &lt;p&gt;There, now it compiles.&amp;#160; However this is obviously not going to pass since we are actually throwing an exception in our method.&amp;#160; But again, or goal here is to execute a test that &lt;em&gt;fails&lt;/em&gt; first.&amp;#160; Then we’ll make our method work.&amp;#160; Just to be sure…&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The failing test" border="0" alt="The failing test" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNNwB5tGI/AAAAAAAAADo/-1Mkhb8VovY/code36.png?imgmax=800" width="704" height="86" /&gt; &lt;/p&gt;  &lt;p&gt;Yep, it fails – good.&amp;#160; Now let’s write the &lt;em&gt;minimum&lt;/em&gt; amount of code to make it pass:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ShippingCalculator class" border="0" alt="ShippingCalculator class" src="http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNOKMLkLI/AAAAAAAAADs/i5H3QU9jo_Q/code48.png?imgmax=800" width="536" height="145" /&gt; &lt;/p&gt;  &lt;p&gt;And re-run our test:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="It passes!" border="0" alt="It passes!" src="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjNOGlkVtI/AAAAAAAAADw/fK8D79wQIlw/codePass15.png?imgmax=800" width="371" height="89" /&gt; &lt;/p&gt;  &lt;p&gt;Awesome!&amp;#160; Now we have a class that satisfies our first requirement.&amp;#160; We can move onto the next requirements by writing more tests and then implementing the code to make them pass.&amp;#160; Eventually we’ll get to a point where we’re ready to refactor this code, which is the final part of red/green/refactor.&lt;/p&gt;  &lt;p&gt;At that point, our Calculate() method will be completely covered by tests so we can refactor without fear!&amp;#160; We know that if we break anything by accident (who me?) the test will slap us upside the head.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-3350701702094883122?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/3350701702094883122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=3350701702094883122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3350701702094883122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/3350701702094883122'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-2-write-my-tests-first.html' title='TDD Part 2: Write My Tests First?'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_Ibq67iO0TPU/SmjNM4FML9I/AAAAAAAAADU/832yprTf5-0/s72-c/confusedmonkey_thumb1.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-1777546023374967290</id><published>2009-07-23T13:49:00.001-07:00</published><updated>2010-11-16T12:15:13.797-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>TDD Part 1: Why Use It?</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Part 1: Why use it?&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_Ibq67iO0TPU/SmjM68u9JMI/AAAAAAAAAC4/98lwPAB_TyU/s1600-h/new_coke_great_taste7.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="new_coke_great_taste" border="0" alt="new_coke_great_taste" align="right" src="http://lh3.ggpht.com/_Ibq67iO0TPU/SmjM7IwWjXI/AAAAAAAAAC8/lrdtNHFjEFQ/new_coke_great_taste_thumb3.jpg?imgmax=800" width="170" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Anytime you are going try something new, there should be a reason, right?&amp;#160; You wouldn’t just go out and spend your hard earned money on a can of New Coke unless you thought it was going to enhance your soft drink refreshment experience.&amp;#160; You have an expectation that the taste could be better, so you try it.&amp;#160; Maybe not a great example since New Coke didn’t work out so well, but you get the idea.&lt;/p&gt;  &lt;p&gt;So that begs the question: Why use TDD? &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I’m sure you could find millions of reasons why you should (or shouldn’t) use TDD out there.&amp;#160; But for me, it comes down to three main points:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;To drive the design of your application. &lt;/li&gt;    &lt;li&gt;So you write better code. &lt;/li&gt;    &lt;li&gt;So your code is “covered”. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Wow that sounds good.&amp;#160; Tell me more.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;TDD – It’s Not Just About Testing&lt;/b&gt;     &lt;br /&gt;This was one of those “huh?” things the first time I heard it.&amp;#160; TDD is as much (if not more) about design as it is about testing.&amp;#160; The idea is that you write your tests first and then write &lt;em&gt;just&lt;/em&gt; enough code to satisfy the test (more on this in the next post).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_Ibq67iO0TPU/SmjM7VeuEkI/AAAAAAAAADA/SQ6wKdeWHxA/s1600-h/regrettesting14.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="regret-testing" border="0" alt="regret-testing" src="http://lh6.ggpht.com/_Ibq67iO0TPU/SmjM7tbfruI/AAAAAAAAADE/cpduyZgdBeQ/regrettesting_thumb10.png?imgmax=800" width="346" height="463" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now this was a little tricky for us because we are &lt;em&gt;not&lt;/em&gt; an agile shop.&amp;#160; We’re more of a waterfall kinda place.&amp;#160; But TDD can still work well even in when using a waterfall methodology.&amp;#160; The key is to not design every tiny detail before you begin coding, but instead to define the basic structure.&lt;/p&gt;  &lt;p&gt;Using our sample described in the &lt;a href="http://mrdustpan.blogspot.com/2009/07/test-driven-development-introduction.html"&gt;introduction&lt;/a&gt;, let’s look at a couple of different ways we could write a design for a method that calculates shipping:&lt;/p&gt;  &lt;p&gt;You could do it like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table border="1" cellspacing="0" bordercolor="#cccccc" cellpadding="5" width="400" bgcolor="#eeeeee"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="398"&gt;           &lt;p&gt;&lt;strong&gt;InvoiceManager.CalculateShipping():&lt;/strong&gt;               &lt;br /&gt;&lt;/p&gt;            &lt;ol&gt;             &lt;li&gt;Receives an OrderDetails parameter. &lt;/li&gt;              &lt;li&gt;Returns a decimal. &lt;/li&gt;              &lt;li&gt;Shipping = OrderDetails.Products.Count * 3 &lt;/li&gt;              &lt;li&gt;If OrderDetails.OrderTotal &amp;gt; 100, Shipping is Shipping *.9. &lt;/li&gt;              &lt;li&gt;If Shipping &amp;gt; 30, Shipping is 30. &lt;/li&gt;           &lt;/ol&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Or like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table border="1" cellspacing="0" bordercolor="#cccccc" cellpadding="5" width="400" bgcolor="#eeeeee"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="398"&gt;           &lt;p&gt;&lt;strong&gt;Calculating Shipping:&lt;/strong&gt;&lt;/p&gt;            &lt;ol&gt;             &lt;li&gt;Create a module that will calculate and return the shipping for an order:                &lt;br /&gt;- Order quantity * 3                 &lt;br /&gt;- If order total &amp;gt; 100, reduce shipping by 10%                 &lt;br /&gt;- Maximum amount for shipping is 30 &lt;/li&gt;           &lt;/ol&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Now although these are very similar, and basically define the same thing (we need to calculate shipping for an order) the first one is much more restrictive, much more dictator-like:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You &lt;em&gt;must&lt;/em&gt; create a class called InvoiceManager! &lt;/li&gt;    &lt;li&gt;You &lt;em&gt;must&lt;/em&gt; create an OrderDetails object, and this object &lt;em&gt;will&lt;/em&gt; have an OrderTotal and a Products collection – do you understand?? &lt;/li&gt;    &lt;li&gt;If you do not create a CalculateShipping() method that takes in an OrderDetails and returns a decimal, you will be promptly shot! &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The second approach leaves you a little bit of room.&amp;#160; What if you write your CalculateShipping() method and you &amp;lt;gasp&amp;gt; change your mind?&amp;#160; You want to take in the order total and order quantity instead of an entire OrderDetails object?&amp;#160; What if you decide you don’t want to name your class InvoiceManager because you realize it’s a &lt;a href="http://www.codinghorror.com/blog/archives/000553.html"&gt;stupid name&lt;/a&gt;?&amp;#160; You have some room to move with regard to the design of the code, but the end result will be the same: something that correctly calculates shipping.&lt;/p&gt;  &lt;p&gt;Now when you’re writing your tests, you can flush out these details as they are needed.&amp;#160; It will help you avoid over-engineering something right from the start.&amp;#160; And it will most likely result in cleaner, less complex code.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Write Better Code&lt;/b&gt;     &lt;br /&gt;In my experience, using TDD helps my code turn out better in a few ways:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;u&gt;No Extraneous Code&lt;/u&gt; – using the “only-write-the-minimum-code-required” principle, you don’t end up with extra stuff.&amp;#160; &lt;em&gt;All&lt;/em&gt; code you write is there because there was a failing test that forced you to write it. &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Smaller, Simpler Objects&lt;/u&gt; – I’ve found that in order to test something, it needs to be simple to test.&amp;#160; This naturally drove me to writing smaller objects that were less complex and basically did only 1 thing (&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;SRP&lt;/a&gt;, anyone?). &lt;/li&gt;    &lt;li&gt;&lt;u&gt;Separation of Concerns&lt;/u&gt; – Similar to the previous point, in order to easily test something you need to have good separation of concerns so you are only testing 1 thing.&amp;#160; More on this in a future post. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Don’t Worry, You’re Covered&lt;/b&gt;     &lt;br /&gt;Warm and fuzzy.&amp;#160; That’s how well written unit tests can make you feel.&amp;#160; You know that your code is solid and, more importantly, that it can be modified without fear.&amp;#160; If you have tests that verify all of the required functionality for some module, you can refactor, modify, extend or otherwise mess with that module – and you know you’re covered.&amp;#160; If you break some existing functionality, your tests will smack you in the face.&amp;#160; It’s a wonderful thing.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-1777546023374967290?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/1777546023374967290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=1777546023374967290' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1777546023374967290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/1777546023374967290'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/tdd-part-1-why-use-it.html' title='TDD Part 1: Why Use It?'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_Ibq67iO0TPU/SmjM7IwWjXI/AAAAAAAAAC8/lrdtNHFjEFQ/s72-c/new_coke_great_taste_thumb3.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-75441442321101539</id><published>2009-07-23T13:42:00.001-07:00</published><updated>2010-11-16T12:14:09.681-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Test Driven Development'/><title type='text'>Test Driven Development: Introduction</title><content type='html'>&lt;ul style="font-size: 0.8em"&gt;   &lt;li&gt;Introduction &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-1-why-use-it.html"&gt;Part 1: Why use it?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-2-write-my-tests-first.html"&gt;Part 2: Write My Tests First?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-keys-to-effective-tdd.html"&gt;Part 3: Keys to Effective TDD&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-1-write-testable-code.html"&gt;Part 3, Key #1: Write Testable Code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-2-write-good-tests.html"&gt;Part 3, Key #2: Write Good Tests&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-3-key-3-using-fakes-and.html"&gt;Part 3, Key #3: Using Fakes and Dependency Injection&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://mrdustpan.blogspot.com/2009/07/tdd-part-4-conclusion.html"&gt;Part 4: Conclusion&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Recently another developer and I have had the privilege of working on a green field project - something that we developers don’t always get a chance to do.&amp;#160; It has been fun, exciting, daunting, frustrating – and above all else, educational.&lt;/p&gt;  &lt;p&gt;One thing that we wanted to try on this project, which we really haven’t done in the past, is unit testing (crazy, huh?).&amp;#160; And I had read about some idea that a bunch of weirdos came up with called “&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;Test Driven Development&lt;/a&gt;” that sounded intriguing.&lt;/p&gt;  &lt;p&gt;So we decided what the heck, let’s TDD this puppy and see what happens.&amp;#160; Of course we didn’t really know anything about TDD, or unit testing in general for that matter.&amp;#160; But with everyone raving about its awesomeness we figured it would just come to us in a zen-like moment of clarity while hacking away at our code.&amp;#160; Needless to say we ran into some bumps along the way, and there were times when we were left scratching our heads saying “I still don’t get it.”&amp;#160; But we learned and failed, and failed and learned, and I feel like we’ve come out the other end of the tunnel with a better understanding of the how’s and why’s of TDD.&lt;/p&gt;  &lt;p&gt;This is the first in what is going to be a series on my experiences and understanding of the TDD process.&amp;#160; &lt;strong&gt;I am by no means an expert – I still consider myself a novice at this&lt;/strong&gt;.&amp;#160; However I do feel that I have learned a ton in the past 7 or 8 months, and I think it could be helpful to others.&amp;#160; Especially those wondering why TDD, and how to get started.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The Sample&lt;/b&gt;     &lt;br /&gt;For all of these posts on TDD, we’re going to need a sample.&amp;#160; So using my great genius I came up with this fake requirements spec:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table border="1" cellspacing="0" bordercolor="#cccccc" cellpadding="5" width="400" bgcolor="#eeeeee"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="398"&gt;           &lt;p&gt;&lt;strong&gt;&lt;u&gt;“Print Invoice” Screen Requirements&lt;/u&gt;&lt;/strong&gt;               &lt;br /&gt;&lt;/p&gt;            &lt;p&gt;Create a “Print Invoice” screen.&amp;#160; When a user enters an order number and clicks the print button, the invoice for that order will be printed.&lt;/p&gt;            &lt;p&gt;The invoice should contain:&lt;/p&gt;            &lt;ul&gt;             &lt;li&gt;Customer Information (customer number, name, shipping address…) &lt;/li&gt;              &lt;li&gt;Order Details (product and quantity information) &lt;/li&gt;              &lt;li&gt;Shipping Costs &lt;/li&gt;              &lt;li&gt;Sales Tax &lt;/li&gt;              &lt;li&gt;Invoice Total                &lt;br /&gt;&lt;/li&gt;           &lt;/ul&gt;            &lt;p&gt;Calculating Shipping: &lt;/p&gt;            &lt;ul&gt;             &lt;li&gt;Standard shipping is $3.00 per item. &lt;/li&gt;              &lt;li&gt;If the order total exceeds $100 there is a 10% discount on shipping. &lt;/li&gt;              &lt;li&gt;There is a maximum shipping charge of $30.                &lt;br /&gt;&lt;/li&gt;           &lt;/ul&gt;            &lt;p&gt;Calculating Sales Tax: &lt;/p&gt;            &lt;ul&gt;             &lt;li&gt;Sales tax is 7% of the order total. &lt;/li&gt;           &lt;/ul&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Now we’re ready to get going. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-75441442321101539?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/75441442321101539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=75441442321101539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/75441442321101539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/75441442321101539'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/07/test-driven-development-introduction.html' title='Test Driven Development: Introduction'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-2410024210589868816</id><published>2009-02-12T06:54:00.001-08:00</published><updated>2009-02-12T06:54:00.839-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>More WCF Goodies</title><content type='html'>&lt;p&gt;&lt;a href="http://notgartner.wordpress.com/2006/12/19/rant-an-error-occured-creating-the-configuration-section-handler-for-systemservicemodelbehaviors/" target="_blank"&gt;This blog post&lt;/a&gt; wonderfully explains this issue in detail, but here’s another FMI post:&lt;/p&gt;  &lt;p&gt;Trying to add a custom endpoint or service behavior to a WCF service?&amp;#160; Be sure that your custom behavior extension in the config file is exactly 100% perfectly correct.&amp;#160; The &amp;lt;add /&amp;gt; element of the behaviorExtension needs to have it’s “type” attribute exactly match your type.&lt;/p&gt;  &lt;p&gt;For example, this entry:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;add name=&amp;quot;myBehavior&amp;quot; type=&amp;quot;MyNamespace.MyClass, MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Is not the same as (notice the lack of spaces):&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;add name=&amp;quot;myBehavior&amp;quot; type=&amp;quot;MyNamespace.MyClass,MyAssembly,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="verd"&gt;So everything, from spaces to version number have to match character for character, or else you’ll get this exception:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element '...' cannot be added to this element.&amp;#160; Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions.&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-2410024210589868816?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/2410024210589868816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=2410024210589868816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2410024210589868816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/2410024210589868816'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2009/02/more-wcf-goodies.html' title='More WCF Goodies'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-6507428718506252112</id><published>2008-12-04T06:19:00.001-08:00</published><updated>2008-12-04T06:19:36.124-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>ASP.NET MVC, jQuery Ajax, FireFox and IIS 6 Combine for a 411 Length Required Error</title><content type='html'>&lt;p&gt;(What a stimulating title) Here's a fun nugget I recently discovered when deploying our ASP.NET MVC application to our dev server. We have a very simple editor that allows you to do basic CRUD operations, that (of course) worked great on my box.&amp;#160; When I deployed it, however, I couldn’t perform a delete when using FireFox.&amp;#160; Worked fine in IE and worked fine in both browsers when running on my machine, using the built in VS web server.&lt;/p&gt;  &lt;p&gt;I opened up FireBug and looked at the response from the server.&amp;#160; It was sending back &lt;font face="Courier New" color="#800000"&gt;&amp;quot;&amp;lt;h1&amp;gt;411 Length Required&amp;lt;/h1&amp;gt;&lt;/font&gt;&amp;quot;.&amp;#160; Weird.&amp;#160; My view was using jQuery Ajax to send the Id of the item to be deleted to my controller – it basically looked like this:&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; DeleteItem()
{
    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(confirm(&lt;span style="color: #006080"&gt;&amp;quot;Are you sure you want to delete this Item?&amp;quot;&lt;/span&gt;))
    {
        $.post(&lt;span style="color: #006080"&gt;&amp;quot;/Item/Delete/&amp;quot;&lt;/span&gt; + $(&lt;span style="color: #006080"&gt;&amp;quot;#ItemId&amp;quot;&lt;/span&gt;).val(),&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(data){
            document.location = &lt;span style="color: #006080"&gt;&amp;quot;/Item/&amp;quot;&lt;/span&gt;;
        },&lt;span style="color: #006080"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;);
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So essentially it would post to &lt;font face="Courier New" color="#800000"&gt;&amp;quot;/Item/Delete/2&lt;/font&gt;&amp;quot; to delete the item with an Id of 2.&lt;/p&gt;

&lt;p&gt;After searching around a bit, I found &lt;a href="http://groups.google.com/group/jquery-en/browse_thread/thread/22828981cf23bdc4" target="_blank"&gt;this post&lt;/a&gt; and realized that I need to send something for the data parameter.&amp;#160; After changing the second parameter in my &lt;font face="Courier New" color="#800000"&gt;$.post()&lt;/font&gt; call from &lt;font face="Courier New" color="#0000ff"&gt;null&lt;/font&gt; to &lt;font face="Courier New" color="#800000"&gt;{}&lt;/font&gt;, it worked like a charm.&amp;#160; Here’s what the post call looks like:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;$.post(&lt;span style="color: #006080"&gt;&amp;quot;/Item/Delete/&amp;quot;&lt;/span&gt; + $(&lt;span style="color: #006080"&gt;&amp;quot;#ItemId&amp;quot;&lt;/span&gt;).val(),{},&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(data){
    document.location = &lt;span style="color: #006080"&gt;&amp;quot;/Item/&amp;quot;&lt;/span&gt;;
},&lt;span style="color: #006080"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-6507428718506252112?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/6507428718506252112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=6507428718506252112' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6507428718506252112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/6507428718506252112'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2008/12/aspnet-mvc-jquery-ajax-firefox-and-iis.html' title='ASP.NET MVC, jQuery Ajax, FireFox and IIS 6 Combine for a 411 Length Required Error'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-8453010463464891743</id><published>2008-12-02T10:20:00.001-08:00</published><updated>2008-12-02T10:26:47.209-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>The contract name 'IContract' could not be found in the list...</title><content type='html'>&lt;p&gt;This is really a &amp;quot;note to self&amp;quot; as I've run into this twice now, and I've had to figure it out twice.&lt;/p&gt;  &lt;p&gt;When trying to add a new WCF service, you might encounter this error:&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;The contract name 'IMyService' could not be found in the list of contracts implemented by the service 'MyService'&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you are certain that your service does in fact implement the interface,&lt;strong&gt; make sure that your service interface is decorated with the ServiceContract and OperationContract attributes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This has happened to me because I’m developing my services using TDD, so I don’t need the attributes on my interface when running my tests.&amp;#160; But when it comes time to actually implement the service, they need to be there.&amp;#160; I guess I should write some tests that verify that my interface has the correct attributes.&lt;/p&gt;

&lt;p&gt;Here’s a sample WCF service interface, for reference:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 250px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; height: 300px; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;
&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.ServiceModel;

&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; MyCompany.MyApp
{
    [ServiceContract(Namespace = &lt;span style="color: #006080"&gt;&amp;quot;ServiceNamespace&amp;quot;&lt;/span&gt;)]
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IMyService
    {
        [OperationContract]
        &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomeStuff(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; parm1);

        [OperationContract]
        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; StuffWasDone();
    }
}&lt;/pre&gt;
&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-8453010463464891743?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/8453010463464891743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=8453010463464891743' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/8453010463464891743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/8453010463464891743'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2008/12/contract-name-could-not-be-found-in.html' title='The contract name &amp;#39;IContract&amp;#39; could not be found in the list...'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3643710353807395912.post-7188898765585748875</id><published>2008-11-14T19:27:00.001-08:00</published><updated>2008-11-14T19:43:01.135-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Posting Complex Types to an ASP.NET MVC Controller using Ajax and jQuery</title><content type='html'>&lt;p&gt;One of the many awesome features in the ASP.NET MVC framework is the built-in model binder support for complex types.&amp;#160; ScottGu has a good explanation of this in his &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/10/16/asp-net-mvc-beta-released.aspx"&gt;post about the beta&lt;/a&gt; version of ASP.NET MVC.&amp;#160; Basically the MVC framework will magically map form post fields to properties on a complex type in a controller method.&amp;#160; So, instead of your controller method looking like this:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Save(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; id, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; price)
{
    ...
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It can look like this:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Save(Widget widget)
{
    ...
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Introducing Ajax into the Mix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I thought it would be cool to have a form that posted to a controller via Ajax, and was able to take advantage of this built-in model binder support.&amp;#160; I was very happy to learn that the ASP.NET MVC framework can also map JSON objects to my complex types.&lt;/p&gt;

&lt;p&gt;Combining this with a little jQuery goodness and you’ve got a pretty easy way to pass complex types from a View to a Controller using Ajax and jQuery.&amp;#160; Let’s look at some code. 
  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Here we have the all important Widget that we will be viewing and saving:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Widget
{
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Id { get; set; }
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;decimal&lt;/span&gt; Price { get; set; }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And this is the main code in my controller class:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Widget()
{
    ViewData.Model = GetWidget();
    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();
}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; JsonResult SaveWidget(Widget widget)
{
    &lt;span style="color: #008000"&gt;// This is where you'd actually save the Widget&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Json(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { Result = String.Format(&lt;span style="color: #006080"&gt;&amp;quot;Saved widget: '{0}' for ${1}&amp;quot;&lt;/span&gt;, widget.Name, widget.Price) });
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The first method, Widget(), is the view method for the “Widget” action.&amp;#160; This is where you’d get the model’s data and bind it to the view.&lt;/p&gt;

&lt;p&gt;The second method, SaveWidget(), is where the actual saving would take place.&amp;#160; Notice how the return type of this method is JsonResult instead of ActionResult.&amp;#160; Also, notice how the method takes in a complex Widget as an input parameter.&lt;/p&gt;

&lt;p&gt;And finally, here’s the pertinent HTML and JavaScript for the view:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;form&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Form1&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;widget.Id&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;widget.Name&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;my widget&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;widget.Price&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;5.43&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Save&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;onclick&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;SaveWidget()&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;form&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; SaveWidget()
{
    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; formData = $(&lt;span style="color: #006080"&gt;&amp;quot;#Form1&amp;quot;&lt;/span&gt;).serializeArray();
    
    $.post(&lt;span style="color: #006080"&gt;&amp;quot;/Home/SaveWidget&amp;quot;&lt;/span&gt;,
    formData,
    &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(data){
        alert(data.Result);
    }, &lt;span style="color: #006080"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;);
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here I’m using the serializeArray() jQuery method to serialize my form data as a JSON object.&lt;/p&gt;

&lt;p&gt;This is pretty simple, and powerful.&amp;#160; I’m able to post a version of my complex type from the view to the controller using Ajax.&amp;#160; And one of the best parts is that I don’t have to write a JavaScript version of my type, or a custom serializer to form up the JSON.&lt;/p&gt;

&lt;p&gt;Of course, this poses a few questions as far as validation and formatting are concerned.&amp;#160; For example, if you post “$5.43” as the Price property (which is a decimal), it will get changed to 0.00 by the MVC framework.&amp;#160; I’ll probably try to figure out a clean way to handle that and I’ll post on it in the future.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3643710353807395912-7188898765585748875?l=blog.mrdustpan.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.mrdustpan.com/feeds/7188898765585748875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3643710353807395912&amp;postID=7188898765585748875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7188898765585748875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3643710353807395912/posts/default/7188898765585748875'/><link rel='alternate' type='text/html' href='http://blog.mrdustpan.com/2008/11/posting-complex-types-to-aspnet-mvc.html' title='Posting Complex Types to an ASP.NET MVC Controller using Ajax and jQuery'/><author><name>MrDustpan</name><uri>http://www.blogger.com/profile/07966091094050073780</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
