<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>Pat Gannon's blog</title>
    <link rel="self" type="application/xml" href="http://patrickgannon-net.access.secure-ssl-servers.biz/Atom.aspx" />
    <subtitle type="html">.NET, SQL Server, Javascript, Agile</subtitle>
    <id>http://patrickgannon-net.access.secure-ssl-servers.biz/Default.aspx</id>
    <author>
        <name>Pat Gannon</name>
        <uri>http://patrickgannon-net.access.secure-ssl-servers.biz/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 1.9.5.177">Subtext</generator>
    <updated>2009-11-07T00:16:08Z</updated>
    <entry>
        <title>Troubleshooting Non-Reproducible Bugs in Visual Studio 2010</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/11/07/troubleshooting-non-reproducible-bugs-in-visual-studio-2010.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/11/07/troubleshooting-non-reproducible-bugs-in-visual-studio-2010.aspx</id>
        <published>2009-11-07T00:16:08-08:00:00</published>
        <updated>2009-11-07T00:16:08Z</updated>
        <content type="html">&lt;p&gt;There are two new features in Visual Studio 2010 that help developers troubleshoot bugs that can't be easily reproduced.  One is IntelliTrace, which seems like it will be of limited usefulness to me because it can’t be done remotely, but it might be more useful for teams that have a dedicated QA staff and/or don't practice TDD.  On the other hand, I watched an episode of Hanselminutes where Scott interviews Tess Fernandez about Debugging Crash Dumps in VS2010, and that technique seems like it could be really useful.&lt;/p&gt;  &lt;p&gt;IntelliTrace is only available in Visual Studio 2010 Ultimate.  It seems to collect the values of all in-scope variables whenever an IntelliTrace event occurs.  Those watched events are configurable (from a long, but pre-determined list), and include things like button clicks, writing to the Debug log, registry access, etc.  If you encounter some non-desirable functionality in an application while debugging (or running their test tool), you can break in the debugger, and then see what the state was whenever one of the watched events occurred.  There is also an option to basically capture the state whenever a method is called, but that entails a significant performance penalty, as one might expect.  I found an article on MSDN that says: “With IntelliTrace, you can debug applications launched from Visual Studio and log files that were created by IntelliTrace or the test tool Test and Lab Manager. You cannot use IntelliTrace with applications launched outside Visual Studio and attached using the Attach to command. IntelliTrace does not support remote debugging of applications that are running on other computers.”  That implies to me that there’s no real way to use this functionality to figure out what happened when a bug occurred on a user’s computer, unfortunately.  That article is here: &lt;a href="http://msdn.microsoft.com/en-us/library/dd264915%28VS.100%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd264915(VS.100).aspx&lt;/a&gt; .  Also note that although you can step backwards in the debugger (and step out of methods to see what the variables were in the calling method) in IntelliTrace, you can only step in increments of IntelliTrace events (which can include method calls if you configured VS that way), so it will step over big chunks of code if they don’t include watched events.&lt;/p&gt;  &lt;p&gt;Here are some posts about how to get started using IntelliTrace: &lt;a href="http://blogs.msdn.com/habibh/archive/2009/10/20/getting-started-with-visual-studio-2010-intellitrace-hello-intellitrace.aspx"&gt;http://blogs.msdn.com/habibh/archive/2009/10/20/getting-started-with-visual-studio-2010-intellitrace-hello-intellitrace.aspx&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/habibh/archive/2009/10/21/the-future-of-debugging-is-here-visual-studio-2010-now-supports-stepping-back-in-the-debugger.aspx"&gt;http://blogs.msdn.com/habibh/archive/2009/10/21/the-future-of-debugging-is-here-visual-studio-2010-now-supports-stepping-back-in-the-debugger.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Debugging crash dumps, however, does seem like something that can be done to troubleshoot undesirable functionality that happened on a user’s computer (or on a production server).  Apparently in Vista and Windows 7, there is functionality in Task Manager such that you can right-click on a process and choose “Create Dump File” which creates a file in “the temp directory”.  (Apparently there are separate apps you can download to generate such dump files with Windows XP, such as “DebugDiag”, but I'm not sure if that works with managed code.)  You can then open the resulting file in Visual Studio 2010 and, provided you have the source code for the application, debug it in “Mixed Mode” (meaning you can see what was happening in managed code as well as in Native code).  Although you can’t step in the debugger when you’ve loaded a dump file, you can see all the values of the variables in memory (by highlighting over them in code just like typical debugging), and using the “Parallel Stacks” window in VS2010, you can get a visualization of the code that all active threads were executing when the dump was generated, and click through to see what all the variables were set to in a given thread when the dump was generated.  It was implied in passing that this will work with applications compiled for .NET 3.5.  It seems to me this would be incredibly useful for troubleshooting a problem that can’t be reproduced.  When the problem happens, just tell the user to create a dump file, send it to development, and then see what was happening with their app at the time.  That screencast is here: &lt;a href="http://channel9.msdn.com/posts/Glucose/Hanselminutes-on-9-Debugging-Crash-Dumps-with-Tess-Ferrandez-and-VS2010/"&gt;http://channel9.msdn.com/posts/Glucose/Hanselminutes-on-9-Debugging-Crash-Dumps-with-Tess-Ferrandez-and-VS2010/&lt;/a&gt;  I'm excited about this functionality, and I'm hoping to be able to spend more time trying to debug Crash Dumps created from some of my company's WinForms applications, and seeing if it is feasible to do from Windows XP (which is installed on many of the workstations running our applications).  When and if that comes to fruition, I'll be writing another post on this topic.&lt;/p&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/16.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/16.aspx</wfw:comment>
        <slash:comments>4</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/16.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/16.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Getting ActiveRecord and NHibernate Working in Medium Trust</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/23/getting-activerecord-and-nhibernate-working-in-medium-trust.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/23/getting-activerecord-and-nhibernate-working-in-medium-trust.aspx</id>
        <published>2009-06-23T22:31:18-07:00:00</published>
        <updated>2009-06-23T22:31:18Z</updated>
        <content type="html">&lt;p&gt;I have spent the last couple of hours trying to figure out how to get &lt;a href="http://www.castleproject.org/activerecord/index.html"&gt;Castle ActiveRecord&lt;/a&gt; working in &lt;a href="http://help.godaddy.com/article/1039"&gt;medium trust&lt;/a&gt; (using &lt;a href="http://www.godaddy.com"&gt;GoDaddy&lt;/a&gt;), and I have finally succeeded (for my purposes).&lt;/p&gt;  &lt;p&gt;Here are the steps I had to take to get this working:&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;* Re-built ActiveRecord to allow partially trusted callers, which entails the following steps: (thanks to &lt;a href="http://forum.castleproject.org/viewtopic.php?t=1439"&gt;this thread on the Castle Project forums&lt;/a&gt;)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Do an SVN Checkout on the Castle project trunk using &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt; or &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt;. The repository is here: &lt;a title="http://svn.castleproject.org:8080/svn/castle/trunk" href="http://svn.castleproject.org:8080/svn/castle/trunk"&gt;http://svn.castleproject.org:8080/svn/castle/trunk&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;2. Navigate to the root directory of the Castle project on your machine and enter the following command:&lt;/p&gt;    &lt;p&gt;SharedLibs\build\NAnt\bin\nant -t:net-3.5 -D:assembly.allow-partially-trusted-callers=true&lt;/p&gt;    &lt;p&gt;Naturally, the build fails (running unit tests), but I was none-the-less able to get the updated DLLs I needed from the build\net-3.5\debug directory under the Castle directory.  I updated all the ActiveRecord-related DLLs (and NHibernate, etc.) that my app was using from the release version of ActiveRecord to this newly-compiled version.  It also now needs Iese.Collections.dll and NHibernate.ByteCode.Castle.dll&lt;/p&gt;    &lt;p&gt;3. I added the following line to my ActiveRecord configuration file (appconfig.xml), which is required by newer versions of NHibernate (thanks to &lt;a href="http://nhforge.org/blogs/nhibernate/archive/2008/11/09/nh2-1-0-bytecode-providers.aspx"&gt;these instructions on NHForge&lt;/a&gt;):&lt;/p&gt;    &lt;p&gt;&amp;lt;add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" /&amp;gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;* Enable &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.allowpartiallytrustedcallersattribute.aspx"&gt;AllowPartiallyTrustedCallers&lt;/a&gt; by adding the following code to AssemblyInfo.cs:&lt;/p&gt;  &lt;p&gt;[assembly: System.Security.AllowPartiallyTrustedCallers]&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;* Place this line after your call to ActiveRecordStarter.Initialize(...): (thanks to &lt;a href="http://nhforge.org/wikis/howtonh/run-in-medium-trust.aspx"&gt;these instructions on NHForge&lt;/a&gt;)    &lt;br /&gt;NHibernate.Cfg.Environment.UseReflectionOptimizer = false;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Apparently getting Lazy Loading to work in Medium Trust is even harder, but there is apparently a tool available called &lt;a href="http://blog.symbiotic-development.com/2008/03/22/nhibernate-proxy-generator/"&gt;NHibernate Proxy Generator&lt;/a&gt; that will enable that to work, although it entails generating proxies at compile-time because Reflection is not allowed under Medium Trust.  Here is the tale of an individual who was apparently able to get this to work: &lt;a title="http://blechie.com/WPierce/archive/2008/02/17/Lazy-Loading-with-nHibernate-Under-Medium-Trust.aspx" href="http://blechie.com/WPierce/archive/2008/02/17/Lazy-Loading-with-nHibernate-Under-Medium-Trust.aspx"&gt;http://blechie.com/WPierce/archive/2008/02/17/Lazy-Loading-with-nHibernate-Under-Medium-Trust.aspx&lt;/a&gt;  At present, I don't need lazy-loading in the application that I'm running in Medium Trust, so I haven't tried it.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Good luck!  Leave a comment if this worked for you, or if you have any problems.&lt;/p&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/15.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/15.aspx</wfw:comment>
        <slash:comments>9</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/15.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/15.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Updated Presentation Materials: Developing REST Web Services using WCF</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/16/updated-presentation-materials-developing-rest-web-services-using-wcf.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/16/updated-presentation-materials-developing-rest-web-services-using-wcf.aspx</id>
        <published>2009-06-16T19:28:13-07:00:00</published>
        <updated>2009-06-16T19:28:13Z</updated>
        <content type="html">&lt;p&gt;Here are the presentation materials that were slightly revised for the second time I grave the WCF/REST presentation (on June 3rd in the South Bay).  Sorry for the delay!&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:c366043b-619f-42d0-ba0a-d726c75c3760" class="wlWriterSmartContent"&gt;&lt;p&gt; &lt;a href="http://www.patrickgannon.net/Images/UpdatedPresentationMaterialsDevelopingRE_11174/RESTDemo.zip" target="_blank"&gt;RESTDemo.zip&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/14.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/14.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/14.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/14.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Presenting on REST/WCF in the South Bay</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/01/presenting-on-restwcf-in-the-south-bay.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/06/01/presenting-on-restwcf-in-the-south-bay.aspx</id>
        <published>2009-06-01T22:10:33-07:00:00</published>
        <updated>2009-06-01T22:10:33Z</updated>
        <content type="html">&lt;p&gt;I am doing my &lt;a href="http://www.patrickgannon.net/archive/2009/04/18/presenting-at-nbnug-on-421-developing-rest-web-services-using.aspx"&gt;Developing REST Web Services using WCF&lt;/a&gt; presentation again for the South Bay chapter of the &lt;a href="http://www.baynetug.org/"&gt;Bay.NET&lt;/a&gt; user group.  It will be Wednesday, June 3rd at the Microsoft’s Silicon Valley conference center at 1065 La Avenida St, Mountain View, CA (Building 1 - room number is still TBD).&lt;/p&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/13.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/13.aspx</wfw:comment>
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/13.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/13.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Developing REST Web Services using WCF - Presentation materials</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/22/developing-rest-web-services-using-wcf---presentation-materials.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/22/developing-rest-web-services-using-wcf---presentation-materials.aspx</id>
        <published>2009-04-22T22:48:21-07:00:00</published>
        <updated>2009-04-22T22:48:21Z</updated>
        <content type="html">&lt;p&gt;As promised in the presentation I did last night for NBNUG, here is my slide deck and sample code for my REST/WCF presentation.  As I mentioned in the presentation, the sample code is purposefully not well-factored, so as not to obscure the core concepts that the code is demonstrating.  The sample code is not at all meant to convey architectural best practices for WCF-based applications, it's essentially an illustration to get folks started working with this technology.&lt;/p&gt;  &lt;p&gt;   &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:5cafb7ec-4bbe-4fb9-aa86-680635a378dc" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;p&gt; &lt;a href="http://www.patrickgannon.net/Images/DevelopingRESTWebServicesusingWCFPresent_13F95/DevelopingRESTWebServicesusingWCF.ppt" target="_blank"&gt;Slide Deck&lt;/a&gt;&lt;br /&gt; &lt;a href="http://www.patrickgannon.net/Images/DevelopingRESTWebServicesusingWCFPresent_13F95/RESTDemo.zip" target="_blank"&gt;Sample Code&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;   &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:62840abe-ef26-4e86-bfdc-33452523a6d3" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/WCF" rel="tag"&gt;WCF&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/REST" rel="tag"&gt;REST&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/Web%20Services" rel="tag"&gt;Web Services&lt;/a&gt;&lt;/div&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/12.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/12.aspx</wfw:comment>
        <slash:comments>11</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/12.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/12.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Presenting at NBNUG on 4/21: Developing REST Web Services using WCF</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/18/presenting-at-nbnug-on-421-developing-rest-web-services-using.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/18/presenting-at-nbnug-on-421-developing-rest-web-services-using.aspx</id>
        <published>2009-04-18T17:51:15-07:00:00</published>
        <updated>2009-04-18T17:51:15Z</updated>
        <content type="html">&lt;p&gt;I am demonstrating how to create a REST-based web service using WCF at the upcoming NBNUG meeting.  Here is the abstract:&lt;/p&gt;  &lt;p&gt;Tuesday, 4/21/2009, meeting at 7:00 PM&lt;/p&gt;  &lt;p&gt;O'Reilly Media in Sebastopol &lt;/p&gt;  &lt;p&gt;&lt;a name="WhereWhenField1"&gt;&lt;/a&gt;1003-1005 Gravenstein Highway North, Sebastopol    &lt;br /&gt;Tarsier Conference Room (between Building B and Building C)    &lt;br /&gt;(8 miles west of Santa Rosa) &lt;/p&gt;  &lt;p&gt;&lt;a name="DescriptionField"&gt;&lt;/a&gt;The presenter will walk through a working REST-based web service (and client), implemented with WCF (Windows Communication Foundation). We will discuss the underlying principles of REST (Representational State Transfer), the motivations for it, and how to create that style of web service using WCF. We will discuss how you can secure these type of web services and finally, we will briefly touch on ADO.NET Data Services (formerly known as Astoria): a technology that automatically exposes a REST web service layer on top of a Linq data source.&lt;/p&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/11.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/11.aspx</wfw:comment>
        <slash:comments>4</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/11.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/11.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Rendering a diff in a web page</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/08/rendering-a-diff-in-a-web-page.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/04/08/rendering-a-diff-in-a-web-page.aspx</id>
        <published>2009-04-08T00:05:06-07:00:00</published>
        <updated>2009-04-08T00:05:06Z</updated>
        <content type="html">&lt;p&gt;Recently in my spare time, I have been working on a web site where developers can post code snippets which they would like to be reviewed by other developers on the web.  Once a code snippet has been posted, other developers can add comments and make a revised version of the code snippet, which will be rendered under the original code snippet as a diff (the difference between the original snippet and the revised snippet).  I have registered myself &lt;a href="http://www.codenuggets.net/"&gt;a domain&lt;/a&gt;, but the site is not ready to be launched yet.  This post is about how I rendered a line-oriented diff in an ASP.NET MVC web page.  I'll write another post to announce the site itself when I launch it.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.patrickgannon.net/Images/Renderingadiffinawebpage_14380/Diff.jpg" target="_blank"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="142" alt="The diffUI" src="http://www.patrickgannon.net/Images/Renderingadiffinawebpage_14380/Diff_thumb.jpg" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h3&gt;The Algorithm&lt;/h3&gt;  &lt;p&gt;After a brief period of trying to figure out my own algorithm for rendering a diff, I decided to do some research on how others have solved the problem.  It seems that it's not quite as easy of a problem to solve as it would seem on the surface, and there has actually been a fair amount of in-depth research done on how to solve it.  I wound up deciding to use &lt;a href="http://blog.menees.com/"&gt;Bill Menee&lt;/a&gt;'s &lt;a href="http://www.menees.com/"&gt;Menees diff library&lt;/a&gt;, which uses the popular Myers algorithm, described in the paper &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927"&gt;An O(ND) Difference Algorithm and its Variations&lt;/a&gt; by Eugene W. Myers.  The paper looks fascinating, and I might be interested in implementing it myself at some point, but for the moment I'm going to use the Menees library.  Here is the abstract to the paper, to give you an overview of how Myers solves the problem.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;The problems of finding a longest common subsequence of two sequences A and B and a shortest edit script        &lt;br /&gt;for transforming A into B have long been known to be dual problems. In this paper, they are shown to be         &lt;br /&gt;equivalent to finding a shortest/longest path in an edit graph. Using this perspective, a simple O(ND) time         &lt;br /&gt;and space algorithm is developed where N is the sum of the lengths of A and B and D is the size of the         &lt;br /&gt;minimum edit script for A and B. The algorithm performs well when differences are small (sequences are         &lt;br /&gt;similar) and is consequently fast in typical applications. The algorithm is shown to have O(N+D2 )         &lt;br /&gt;expected-time performance under a basic stochastic model. A refinement of the algorithm requires only         &lt;br /&gt;O(N) space, and the use of suffix trees leads to an O(NlgN +D2 ) time variation.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;The Code&lt;/h3&gt;  &lt;p&gt;Here's the code that I came up with to render a diff created by the Menees library.&lt;/p&gt;  &lt;p&gt;The model and view-data:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Menees.DiffUtils;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; CodeReview.Models&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="rem"&gt;/// Represents a chunk of source code&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SourceCode&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Id { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _title = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Title &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            get&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; _title;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            set&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;                _title = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Description { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Code { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; CreatedBy { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;Comment&amp;gt; Comments { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; _lines = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; Lines&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            get&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (_lines == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;                    _lines = GetLines(Code);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; _lines;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsValid&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (GetRuleViolations().Count() == 0); }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SourceCode(&lt;span class="kwrd"&gt;string&lt;/span&gt; code)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;            : &lt;span class="kwrd"&gt;this&lt;/span&gt;()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;            Code = code;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SourceCode()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;            Comments = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Comment&amp;gt;();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;Difference&amp;gt; Diff(SourceCode compareWith)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;            List&amp;lt;Difference&amp;gt; differences = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Difference&amp;gt;();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;            IList a = Lines;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;            IList b = compareWith.Lines;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;            TextDiff diff = &lt;span class="kwrd"&gt;new&lt;/span&gt; TextDiff((&lt;span class="kwrd"&gt;int&lt;/span&gt;)HashType.HashCode, &lt;span class="kwrd"&gt;false&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;, 0);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;            EditScript script = diff.Execute(a, b);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Edit edit &lt;span class="kwrd"&gt;in&lt;/span&gt; script)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  76:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  77:  &lt;/span&gt;                differences.Add(ConvertEditToDifference(edit, compareWith));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  78:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  79:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  80:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; differences;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  81:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  82:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  83:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; GetLines(&lt;span class="kwrd"&gt;string&lt;/span&gt; code)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  84:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  85:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; code.Split(&lt;span class="str"&gt;'\n'&lt;/span&gt;).ToList();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  86:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  87:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  88:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; Difference ConvertEditToDifference(Edit edit, SourceCode compareWith)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  89:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  90:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Difference()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  91:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  92:  &lt;/span&gt;                LineNumber = edit.StartA + 1,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  93:  &lt;/span&gt;                Text = GetChangeText(edit, compareWith),&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  94:  &lt;/span&gt;                Type = ConvertEditTypeToDifferenceType(edit.Type),&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  95:  &lt;/span&gt;                NumberOfLines = edit.Length&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  96:  &lt;/span&gt;            };&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  97:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  98:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  99:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetChangeText(Edit edit, SourceCode compareWith)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 100:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 101:  &lt;/span&gt;            StringBuilder changeText = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 102:  &lt;/span&gt;            SourceCode textSource;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 103:  &lt;/span&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; lineNumberInTextSource;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 104:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 105:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (edit.Type == EditType.Insert)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 106:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 107:  &lt;/span&gt;                textSource = compareWith;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 108:  &lt;/span&gt;                lineNumberInTextSource = edit.StartB;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 109:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 110:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 111:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 112:  &lt;/span&gt;                textSource = &lt;span class="kwrd"&gt;this&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 113:  &lt;/span&gt;                lineNumberInTextSource = edit.StartA;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 114:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 115:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 116:  &lt;/span&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; edit.Length; i++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 117:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 118:  &lt;/span&gt;                changeText.Append(textSource.Lines[lineNumberInTextSource + i]);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 119:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 120:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 121:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; changeText.ToString();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 122:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 123:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 124:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; DifferenceType ConvertEditTypeToDifferenceType(EditType editType)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 125:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 126:  &lt;/span&gt;            &lt;span class="kwrd"&gt;switch&lt;/span&gt; (editType)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 127:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 128:  &lt;/span&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; EditType.Change:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 129:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; DifferenceType.Change;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 130:  &lt;/span&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; EditType.Delete:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 131:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; DifferenceType.Removal;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 132:  &lt;/span&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; EditType.Insert:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 133:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; DifferenceType.Addition;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 134:  &lt;/span&gt;                &lt;span class="kwrd"&gt;default&lt;/span&gt;:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 135:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Unexpected edit type: "&lt;/span&gt; + editType, &lt;span class="str"&gt;"editType"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 136:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 137:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 138:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 139:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerable&amp;lt;RuleViolation&amp;gt; GetRuleViolations()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 140:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 141:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (String.IsNullOrEmpty(Title))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 142:  &lt;/span&gt;                &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; RuleViolation(&lt;span class="str"&gt;"Title is required"&lt;/span&gt;, &lt;span class="str"&gt;"Title"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 143:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 144:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (String.IsNullOrEmpty(Code))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 145:  &lt;/span&gt;                &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; RuleViolation(&lt;span class="str"&gt;"Code is required"&lt;/span&gt;, &lt;span class="str"&gt;"Code"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 146:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 147:  &lt;/span&gt;            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 148:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 149:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 150:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Validate()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 151:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 152:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!IsValid)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 153:  &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ApplicationException(&lt;span class="str"&gt;"Rule violations prevent saving"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 154:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 155:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 156:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 157:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Difference&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 158:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 159:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DifferenceType Type { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 160:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Text { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 161:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; LineNumber { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 162:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NumberOfLines { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 163:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 164:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 165:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 166:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; CodeReview.ViewData&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 167:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 168:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ShowSourceCodeViewData&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 169:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 170:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RenderedOriginal { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 171:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;CommentViewData&amp;gt; Comments { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 172:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 173:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ShowSourceCodeViewData()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 174:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 175:  &lt;/span&gt;            Comments = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;CommentViewData&amp;gt;();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 176:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 177:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 178:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 179:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CommentViewData&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 180:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 181:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RenderedOriginal { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 182:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RenderedRevised { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 183:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Text { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 184:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 185:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 186:  &lt;/span&gt; &lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;style type="text/css"&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;The controller action and supporting methods:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Show(&lt;span class="kwrd"&gt;int&lt;/span&gt;? id)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;            SourceCode original = _repository.GetById(id.Value);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] originalLines = original.Lines.ToArray();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            ShowSourceCodeViewData viewData = &lt;span class="kwrd"&gt;new&lt;/span&gt; ShowSourceCodeViewData();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            viewData.RenderedOriginal = ConvertFromPlainTextToHtml(original.Code);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Comment comment &lt;span class="kwrd"&gt;in&lt;/span&gt; original.Comments)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                StringBuilder originalBuilder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder(); &lt;span class="rem"&gt;//the buffer for displaying the original version (on the left side of the diff)&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                StringBuilder editedBuilder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder(); &lt;span class="rem"&gt;//the buffer for displaying the revised version (on the right side of the diff)&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                &lt;span class="kwrd"&gt;string&lt;/span&gt;[] editedLines = comment.Revision.Lines.ToArray();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                List&amp;lt;Difference&amp;gt; differences = original.Diff(comment.Revision);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                &lt;span class="kwrd"&gt;int&lt;/span&gt; originalLineNumber = 0;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                &lt;span class="kwrd"&gt;int&lt;/span&gt; editedLineNumber = 0;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                CommentViewData commentViewData = &lt;span class="kwrd"&gt;new&lt;/span&gt; CommentViewData();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Difference difference &lt;span class="kwrd"&gt;in&lt;/span&gt; differences)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                    &lt;span class="rem"&gt;//put all unchanged lines leading up to this difference into both buffers&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;for&lt;/span&gt; (; originalLineNumber &amp;lt; (difference.LineNumber - 1); originalLineNumber++, editedLineNumber++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                        originalBuilder.Append(RenderLineHtml(DifferenceType.NoChange, originalLineNumber, originalLines[originalLineNumber]));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                        editedBuilder.Append(RenderLineHtml(DifferenceType.NoChange, editedLineNumber, editedLines[editedLineNumber]));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (difference.Type == DifferenceType.Addition)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;string&lt;/span&gt; differenceText = difference.Text;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (differenceText.EndsWith(&lt;span class="str"&gt;"\r"&lt;/span&gt;))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;                            differenceText = differenceText.Substring(0, differenceText.Length - 1);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;string&lt;/span&gt;[] lines = differenceText.Split(&lt;span class="str"&gt;'\r'&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;                        &lt;span class="rem"&gt;//put added lines only into the buffer for the revised version, and add blank space to the buffer for the original version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; line &lt;span class="kwrd"&gt;in&lt;/span&gt; lines)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;                        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;                            editedBuilder.Append(RenderLineHtml(difference.Type, editedLineNumber, line));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;                            originalBuilder.AppendLine();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;                            editedLineNumber++;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;                        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (difference.Type == DifferenceType.Removal)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;string&lt;/span&gt; differenceText = difference.Text;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (differenceText.EndsWith(&lt;span class="str"&gt;"\r"&lt;/span&gt;))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;                            differenceText = differenceText.Substring(0, differenceText.Length - 1);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;string&lt;/span&gt;[] lines = differenceText.Split(&lt;span class="str"&gt;'\r'&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;                        &lt;span class="rem"&gt;//put removed lines only into the buffer for the original version, and add blank space to the buffer for the revised version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; line &lt;span class="kwrd"&gt;in&lt;/span&gt; lines)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;                        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;                            originalBuilder.Append(RenderLineHtml(difference.Type, originalLineNumber, line));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;                            editedBuilder.AppendLine();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;                            originalLineNumber++;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;                        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (difference.Type == DifferenceType.Change)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt;                        &lt;span class="rem"&gt;//put revised version of changed line into buffer for revised version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;                        editedBuilder.Append(RenderLineHtml(difference.Type, editedLineNumber, editedLines[editedLineNumber]));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;                        &lt;span class="rem"&gt;//put original version of changed line into buffer for original version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;                        originalBuilder.Append(RenderLineHtml(difference.Type, originalLineNumber, difference.Text));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;                        editedLineNumber++;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;                        originalLineNumber++;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;                &lt;span class="rem"&gt;//put all remaining unchanged lines into buffer for original version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  76:  &lt;/span&gt;                &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = originalLineNumber; i &amp;lt; originalLines.Length; i++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  77:  &lt;/span&gt;                    originalBuilder.Append(RenderLineHtml(DifferenceType.NoChange, i, originalLines[i]));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  78:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  79:  &lt;/span&gt;                &lt;span class="rem"&gt;//put all remaining unchanged lines into buffer for revised version&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  80:  &lt;/span&gt;                &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = editedLineNumber; i &amp;lt; editedLines.Length; i++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  81:  &lt;/span&gt;                    editedBuilder.Append(RenderLineHtml(DifferenceType.NoChange, i, editedLines[i]));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  82:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  83:  &lt;/span&gt;                commentViewData.RenderedOriginal = ConvertFromPlainTextToHtml(originalBuilder.ToString());&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  84:  &lt;/span&gt;                commentViewData.RenderedRevised = ConvertFromPlainTextToHtml(editedBuilder.ToString());&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  85:  &lt;/span&gt;                commentViewData.Text = comment.Text;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  86:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  87:  &lt;/span&gt;                viewData.Comments.Add(commentViewData);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  88:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  89:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  90:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; View(viewData);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  91:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  92:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  93:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConvertFromPlainTextToHtml(&lt;span class="kwrd"&gt;string&lt;/span&gt; plainText)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  94:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  95:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; plainText.Replace(&lt;span class="str"&gt;"\r"&lt;/span&gt;, &lt;span class="str"&gt;"&amp;lt;br/&amp;gt;"&lt;/span&gt;).Replace(&lt;span class="str"&gt;"\n"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;).Replace(&lt;span class="str"&gt;"  "&lt;/span&gt;, &lt;span class="str"&gt;"&amp;amp;nbsp;&amp;amp;nbsp;"&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  96:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  97:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  98:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RenderLineHtml(DifferenceType differenceType, &lt;span class="kwrd"&gt;int&lt;/span&gt; lineNumber, &lt;span class="kwrd"&gt;string&lt;/span&gt; lineText)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  99:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 100:  &lt;/span&gt;            &lt;span class="rem"&gt;//the line will be styled according to the type of change that was made&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 101:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"&amp;lt;div class=\"{0}\"&amp;gt;{1}: {2}&amp;lt;/div&amp;gt;"&lt;/span&gt;, differenceType.ToString().ToLower(), lineNumber, lineText);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt; 102:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The view:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre&gt;&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (CommentViewData comment &lt;span class="kwrd"&gt;in&lt;/span&gt; Model.Comments)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;="comment_body"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= comment.Text &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;="editingArea"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;="originalCode"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            Original:&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= comment.RenderedOriginal &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;="editedCode"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;            Edited:&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= comment.RenderedRevised &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;="height: 500px"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;&lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;style type="text/css"&gt;&lt;![CDATA[csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
]]&gt;&lt;/style&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;The CSS:&lt;/pre&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;.originalCode { float: left; border: thin solid black; padding: 10px 10px 10px 10px; width: 450px; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.editedCode { float: right; border: thin solid black; padding: 10px 10px 10px 10px; position: absolute; left: 600px; width: 450px; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.editingArea { } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.addition { background-color: Black; color: green } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.removal { background-color: Black; color: red } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.change { background-color: Black; color: white } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.comment_body { font-style: italic; font-weight: bold; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.comment_header { font-weight: bold; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Title { width: 700px; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Description { width: 700px; height: 150px; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Code { width: 700px; height: 300px; } &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is going to need some work before it's ready for prime time (the HTML conversion and CSS need work, and the controller method should be broken out into smaller methods, perhaps using a command pattern or something, etc.), but I figured it was enough to get you going if you're thinking about implementing something like this yourself.  (This approach could make for some very nice build notification emails, IMO.)  Did I leave anything important out?  Is there a better or easier way to do this?  Is there a glaring bug?  Leave a comment!&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b54fe025-6f69-434c-9ade-d1b707ef7d50" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/asp.net" rel="tag"&gt;asp.net&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/mvc" rel="tag"&gt;mvc&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/algorithms" rel="tag"&gt;algorithms&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/diff" rel="tag"&gt;diff&lt;/a&gt;&lt;/div&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/10.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/10.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/10.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/10.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Upgrading our site to MVC RC</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/02/05/upgrading-our-site-to-mvc-rc.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/02/05/upgrading-our-site-to-mvc-rc.aspx</id>
        <published>2009-02-05T22:22:44-08:00:00</published>
        <updated>2009-02-05T22:22:44Z</updated>
        <content type="html">&lt;p&gt;At &lt;a href="http://www.hsihealth.com"&gt;work&lt;/a&gt;, we have a web application implemented using the &lt;a href="http://www.asp.net/mvc/"&gt;ASP.NET MVC&lt;/a&gt; Framework.  This week, I upgraded that site from MVC beta to &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=f4e4ee26-4bc5-41ed-80c9-261336b2a5b6&amp;amp;displaylang=en"&gt;MVC Release Candidate&lt;/a&gt;.  The &lt;a href="http://www.microsoft.com/downloads/info.aspx?na=46&amp;amp;p=1&amp;amp;SrcDisplayLang=en&amp;amp;SrcCategoryId=&amp;amp;SrcFamilyId=f4e4ee26-4bc5-41ed-80c9-261336b2a5b6&amp;amp;u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f8%2fF%2fF%2f8FF09794-DC16-4B0B-A11F-B69DA49B89DE%2fASP.NET+MVC+-+RC+Release+Notes.doc&amp;amp;oRef=http%3a%2f%2fwww.asp.net%2fmvc%2f&amp;quot;"&gt;release notes&lt;/a&gt; had some important information about editing the web.config so that you don't need a code-behind for your views, but all it tells you about upgrading the rest of your code-base is that you should upgrade the MVC assemblies that your application is referencing and then fix the compiler errors.  Even after reading about the various changes in the RC, I still had a little trouble figuring out how to adapt our code to work with the various breaking changes, so I figured I would outline some of the issues I ran into here, and how I resolved them, to save you some time if you haven't gotten around to doing this upgrade yet.  Here goes...&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ModelBinderResult no longer exists.  BindModel() should now take a ControllerContext as well as a ModelBindingContext parameter, and it should return the model itself, rather than wrapping it in a ModelBinderResult&lt;/li&gt;    &lt;li&gt;IValueProvider went away - use FormCollection instead to retrieve form values&lt;/li&gt;    &lt;li&gt;The value provider parameter to UpdateModel is now of type IDictionary&amp;lt;string, ValueProviderResult&amp;gt;, rather than IValueProvider (since IValueProvider no longer exists).  You must call ToValueProvider() on your FormCollection and pass that to UpdateModel.&lt;/li&gt;    &lt;li&gt;ModelBindingContext no longer has a "Controller" property.  If you're trying to access that from the BindModel method in a model binder, access it from the new ControllerContext parameter instead.&lt;/li&gt;    &lt;li&gt;ModelBindingContext.ValueProvider is now of type IDictionary&amp;lt;string, ValueProviderResult&amp;gt; (not IValueProvider since that no longer exists), so any places where you're calling GetValue() on that, you will need to replace it with a call to the indexer (eg. bindingContext.ValueProvider[fieldName] instead of bindingContext.ValueProvider.GetValue(fieldName)).  Also note that when you attempt to obtain a value from a generic Dictionary for a key that does not exist, you will get a KeyNotFoundException, whereas GetValue() simply returned null, so you will need to add a check that the key exists before retrieving a value from the collection.&lt;/li&gt;    &lt;li&gt;The ModelBindingContext constructor now takes zero arguments instead of seven.  If you're instantiating a ModelBindingContext in a unit test, rather than passing everything in on the constructor, you'll want to set     &lt;br /&gt; the ValueProvider, ModelType and Model properties (the controller is no longer set on the ModelBindingContext - its set in the ControllerContext, and all the other constructor parameters we were passing null for).&lt;/li&gt;    &lt;li&gt;RedirectToRouteResult.Values is now RedirectToRouteResult.RouteValues&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Good luck and God speed!&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:550bed62-0a64-4abf-8045-2a32ba6cd715" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/asp.net" rel="tag"&gt;asp.net&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/.net" rel="tag"&gt;.net&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/framework" rel="tag"&gt;framework&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/patterns" rel="tag"&gt;patterns&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/mvc" rel="tag"&gt;mvc&lt;/a&gt;&lt;/div&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/9.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/9.aspx</wfw:comment>
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/9.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/9.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Migrating TFS: Point your build server at the new TFS server</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/01/14/migrating-tfs-point-your-build-server-at-the-new-tfs.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2009/01/14/migrating-tfs-point-your-build-server-at-the-new-tfs.aspx</id>
        <published>2009-01-14T23:44:43-08:00:00</published>
        <updated>2009-01-14T23:44:43Z</updated>
        <content type="html">&lt;h3&gt;The Migration&lt;/h3&gt;  &lt;p&gt;Today I finished migrating TFS from a VM to a newly re-purposed machine.  The VM was on an overloaded host box and TFS was a bit sluggish.  Yesterday, I followed Microsoft's painstaking instructions on &lt;a href="http://msdn.microsoft.com/en-us/library/ms404869.aspx"&gt;How to Move Your Team Foundation Server from One Hardware Configuration To Another&lt;/a&gt;.  This morning I updated our TFS build scripts so that all the file paths were valid on the new box, and then I refreshed the Version Control Cache on the build server by using the "tf workspaces /s:&lt;a href="http://ApplicationTierServerName:Port"&gt;http://ApplicationTierServerName:Port&lt;/a&gt;" command (the colon after the "/s" is a needed variation on the command given in Microsoft's instructions on &lt;a href="http://msdn.microsoft.com/en-us/library/cc716728.aspx"&gt;How to Refresh the Data Caches on Client Computers&lt;/a&gt;).  To my dismay, when I ran a build, it failed almost immediately with an error indicating it was trying to access something like vstfs:///Version_Control/Versioned_Items, and the build notification window on the build server still showed the old TFS server name.  I poked around the various TFS databases and a few other places to see if I could find the old server name, but I did not (or at least not anywhere relevant).  I decided to have a look at the .config file being used by the Visual Studio Team Foundation Build service executable, and there was a setting in there for a TFS server URI, but the value was blank.  The comment above the setting indicates that it overrides the setting in the registry under "HKCU".  I figured that if the old server name was in the registry, I would prefer to update that than override it with the new server name.  (No point in having old server names lurking around.)&lt;/p&gt;  &lt;h3&gt;Re-configuring TFS Build&lt;/h3&gt;  &lt;p&gt;After a quick search in the registry (using regedt32 of course), I found the "AllowedTeamServer" key in HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\TeamFoundation\Build\Service, and it was set to the old TFS server URI.  I updated this setting (always exercise caution when modifying your registry!) to be the URI of the new TFS server (&lt;a href="http://[server]:8080/"&gt;http://[server]:8080/&lt;/a&gt;), and then I re-started the Visual Studio Team Foundation Build service, and voila! the next build I kicked off succeeded.  Unfortunately the build notification window on the build server still shows the old TFS server name, but I don't anticipate that being a problem.&lt;/p&gt;  &lt;h3&gt;Retrospective&lt;/h3&gt;  &lt;p&gt;Over-all, Microsoft's aforementioned &lt;a href="http://msdn.microsoft.com/en-us/library/ms404869.aspx"&gt;instructions for migrating TFS to a new server&lt;/a&gt; worked pretty well (after muddling through the usual smattering of security issues), but the fact that properly re-configuring TFS Build to point to a new TFS server (which one would think would be a somewhat common operation, if not frequent, per se) requires a "reg hack" is a little annoying to me, and the fact that this step is not documented in the migration instructions is a significant over-sight.&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:599bfbef-4f98-4242-b94c-2f99f3c3f8f9" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/tfs" rel="tag"&gt;tfs&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/build" rel="tag"&gt;build&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/tfsbuild_customization" rel="tag"&gt;tfsbuild_customization&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/tfbuild" rel="tag"&gt;tfbuild&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/teamfoundationserver" rel="tag"&gt;teamfoundationserver&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/teamsystem" rel="tag"&gt;teamsystem&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/continuousintegration" rel="tag"&gt;continuousintegration&lt;/a&gt;&lt;/div&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/8.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/8.aspx</wfw:comment>
        <slash:comments>5</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/8.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/8.aspx</trackback:ping>
    </entry>
    <entry>
        <title>BDD-style feature tests using IronRuby and RSpec/Cucumber</title>
        <link rel="self" type="text/html" href="http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2008/10/23/bdd-style-feature-tests-using-ironruby-and-rspeccucumber.aspx" />
        <id>http://patrickgannon-net.access.secure-ssl-servers.biz/archive/2008/10/23/bdd-style-feature-tests-using-ironruby-and-rspeccucumber.aspx</id>
        <published>2008-10-23T00:54:16-07:00:00</published>
        <updated>2008-10-23T00:54:16Z</updated>
        <content type="html">&lt;h3&gt;Introduction&lt;/h3&gt;  &lt;p&gt;BDD (&lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development"&gt;Behavior Driven Development&lt;/a&gt;) is a specialization of TDD (&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;Test Driven Development&lt;/a&gt;) that encapsulates a set of best practices espoused by the most successful TDD gurus.  The main theme is focusing on behavior rather than implementation in your tests.  A great tool for verifying behavior (writing BDD-style tests) is &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt;, and now it can be used to test .NET code.&lt;/p&gt;  &lt;p&gt;To get more information on BDD, read &lt;a href="http://dannorth.net/introducing-bdd"&gt;Dan North's Introduction to BDD&lt;/a&gt;.  To get some background information on TDD, read Scott Bellware's &lt;a href="http://web.archive.org/web/20071013075140/http://codebetter.com/blogs/scott.bellware/archive/2005/11/22/134954.aspx"&gt;classic Red-Green-Refactor post&lt;/a&gt; or read Kent Beck's &lt;a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530"&gt;TDD By Example&lt;/a&gt; (this one's on my to-do list, but I've heard great things about it).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; is a unit testing tool for &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; that provides an internal DSL which supports nice BDD-style specifications.  An example of that syntax is below.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;span style="font-size: 10pt; color: #666666; font-family: " courier="courier" new??="new??"&gt;# bowling_spec.rb      &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;require &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #771100; font-family: " courier="courier" new??="new??"&gt;'&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #dd2200; font-family: " courier="courier" new??="new??"&gt;bowling&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #771100; font-family: " courier="courier" new??="new??"&gt;'&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt; &lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;describe &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: " courier="courier" new??="new??"&gt;Bowling&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;do        &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;before(&lt;/span&gt;&lt;span style="font-size: 10pt; color: #aa6600; font-family: " courier="courier" new??="new??"&gt;:each&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;) &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;do        &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #3333bb; font-family: " courier="courier" new??="new??"&gt;@bowling&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt; = &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: " courier="courier" new??="new??"&gt;Bowling&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;.new      &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt; &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;it &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #771100; font-family: " courier="courier" new??="new??"&gt;"&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #dd2200; font-family: " courier="courier" new??="new??"&gt;should score 0 for gutter game&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0f0; color: #771100; font-family: " courier="courier" new??="new??"&gt;"&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;do        &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #0000dd; font-family: " courier="courier" new??="new??"&gt;20&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;.times { &lt;/span&gt;&lt;span style="font-size: 10pt; color: #3333bb; font-family: " courier="courier" new??="new??"&gt;@bowling&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;.hit(&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #0000dd; font-family: " courier="courier" new??="new??"&gt;0&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;) }      &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #3333bb; font-family: " courier="courier" new??="new??"&gt;@bowling&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;.score.should == &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #0000dd; font-family: " courier="courier" new??="new??"&gt;0        &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;end        &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: " courier="courier" new??="new??"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: " courier="courier" new??="new??"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;RSpec also provides an external DSL (the RSpec Story Runner) that allows you to create executable plain-English feature documentation in the Given/When/Then format typical of BDD tests.  This tool has been broken out into its own project called &lt;a href="http://github.com/aslakhellesoy/cucumber/wikis"&gt;Cucumber&lt;/a&gt;, and an example of the syntax is below (from the RSpec website).&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;pre&gt;Feature: transfer from savings to checking account&lt;br /&gt;  As a savings account holder&lt;br /&gt;  I want to transfer money from my savings account to my checking account&lt;br /&gt;  So that I can get cash easily from an ATM &lt;/pre&gt;

&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  Scenario: savings account has sufficient funds&lt;br /&gt;    Given my savings account balance is $100&lt;br /&gt;    And my checking account balance is $10&lt;br /&gt;    When I transfer $20 from savings to checking&lt;br /&gt;    Then my savings account balance should be $80&lt;br /&gt;    And my checking account balance should be $30&lt;/pre&gt;

&lt;pre&gt; &lt;/pre&gt;

&lt;pre&gt;  Scenario: savings account has insufficient funds&lt;br /&gt;    Given my savings account balance is $50&lt;br /&gt;    And my checking account balance is $10&lt;br /&gt;    When I transfer $60 from savings to checking&lt;br /&gt;    Then my savings account balance should be $50&lt;br /&gt;    And my checking account balance should be $10&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;As the RSpec website says "Each Given, When and Then is a Step. The Ands are each the same kind as the previous Step. Steps get defined in Ruby like this (detail left out for brevity) in steps.rb (in the same directory in this example):"&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: 'Courier New'"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: 'Courier New'"&gt;Given&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;^my (.*) account balance is &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\d&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;+)$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; |account_type, amount| 
    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;create_account(account_type, amount) 

    &lt;br /&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;end 
      &lt;br /&gt;

      &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: 'Courier New'"&gt;When&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;^I transfer &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\d&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;+) from (.*) to (.*)$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; |amount, source_account, 
    &lt;br /&gt;target_account| 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;get_account(source_account).transfer(amount).to(get_account(target_account)) 

    &lt;br /&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;end 
      &lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #003366; font-family: 'Courier New'"&gt;Then&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;^my (.*) account balance should be &lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #0044dd; font-family: 'Courier New'"&gt;\d&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #880088; font-family: 'Courier New'"&gt;+)$&lt;/span&gt;&lt;span style="font-size: 10pt; background: #fff0ff; color: #440044; font-family: 'Courier New'"&gt;/&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt; |account_type, amount| 
    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #110000; font-family: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;get_account(account_type).should have_a_balance_of(amount) 

    &lt;br /&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;end&lt;/span&gt;&lt;/b&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;span style="font-size: 10pt; color: #008800; font-family: 'Courier New'"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;

&lt;h3&gt;Getting RSpec and Cucumber set up to work with .NET&lt;/h3&gt;

&lt;p&gt;The first thing you need to do to start verifying the behavior of .NET code using RSpec is to install &lt;a href="http://www.ironruby.net/"&gt;IronRuby&lt;/a&gt;.  In theory, it's also possible to use RSpec to test .NET code by using &lt;a href="http://jruby.codehaus.org/"&gt;jRuby&lt;/a&gt; and Java's interoperability with .NET, and in fact there's an example of that approach that comes bundled with Cucumber, but I thought this was one too many layers of interoperability (jRuby -&amp;gt; Java -&amp;gt; .NET) for an approach I am going to attempt to use to verify behavior in the majority of code I write.  Also, Cucumber's web site says "When &lt;a href="http://www.ironruby.net/"&gt;IronRuby&lt;/a&gt; matures it can be used to 'test' .NET code too", so I took that as a hint that the jRuby way might be problematic in the long run.  Finally, I wanted an excuse to play with IronRuby :-)  To get the latest version of IronRuby, you must install &lt;a href="http://tortoisesvn.net/downloads"&gt;TortoiseSVN&lt;/a&gt; and then do an SVN Checkout from &lt;a title="http://ironruby.rubyforge.org/svn/trunk" href="http://ironruby.rubyforge.org/svn/trunk"&gt;http://ironruby.rubyforge.org/svn/trunk&lt;/a&gt;.  Open IronRuby.sln in Visual Studio (telling it to "Load Projects Normally" if prompted) and Build Solution.  There is a ZIP of IronRuby you can download from rubyforge also, but that didn't work too well for me, so I wouldn't recommend it.  (I suspect it's a significantly outdated release.)&lt;/p&gt;

&lt;p&gt;In order to obtain &lt;a href="http://github.com/aslakhellesoy/cucumber/wikis"&gt;Cucumber&lt;/a&gt; and all its dependencies, download and install the latest version of the &lt;a href="http://rubyforge.org/frs/?group_id=167&amp;amp;release_id=26150"&gt;Ruby One-Click Installer&lt;/a&gt; (henceforth referred to as regular Ruby).  At the command line (from any folder), type "gem Cucumber" and answer "Y" when it asks you to install each of the dependencies.  The reason that regular Ruby (rather than IronRuby) is used for this step is because I was not able to get &lt;a href="http://www.rubygems.org/"&gt;RubyGems&lt;/a&gt; to work on IronRuby.&lt;/p&gt;

&lt;p&gt;Next, copy the contents of all the gems you just downloaded from C:\ruby\lib\ruby\gems\1.8\gems (assuming you installed regular Ruby to C:\ruby) to C:\Projects\IronRuby\trunk\lib (assuming you checked out the IronRuby trunk to C:\Projects\IronRuby\trunk).  A list of the gems you will need to copy is as follows:&lt;/p&gt;

&lt;p&gt;cucumber 
  &lt;br /&gt;hoe 

  &lt;br /&gt;polyglot 

  &lt;br /&gt;rake 

  &lt;br /&gt;rubyforge 

  &lt;br /&gt;rspec 

  &lt;br /&gt;term-ansicolor

  &lt;br /&gt;treetop&lt;/p&gt;

&lt;p&gt;Note that you will specifically want to copy only the contents of the "lib" directory of each of these gems.  (For example, C:\ruby\lib\ruby\gems\1.8\gems\treetop-1.2.4\lib\treetop.rb will be copied to C:\Projects\IronRuby\trunk\lib\treetop.rb and similarly the C:\ruby\lib\ruby\gems\1.8\gems\treetop-1.2.4\lib\treetop folder will be copied to C:\Projects\IronRuby\trunk\lib\treetop.)  Copying the contents of the "lib" folder of each of these gems was the only way I could manage to get IronRuby to recognize all of them at the same time.  I have heard that setting the GEM_PATH environment variable to the location where you have put your gems will enable IronRuby to recognize them, but that didn't work for me, which necessitated the kludgy step I just described.&lt;/p&gt;

&lt;p&gt;Next, you will need to modify a few files within RSpec and Cucumber to get them to work with IronRuby.  the modifications are as follows (paths are relative to C:\Projects\IronRuby\trunk):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In lib\cucumber\formatters\pretty_formatter.rb, find the "source_comment" method, comment out the body of it, and add simply two double-quotes (an empty string) as the new body of the method.  This is because the executable file location doesn't seem to be available in IronRuby.  (The commented out code is what would normally print the name of the file and the line number of each code definition referred to by the specification.) &lt;/li&gt;

  &lt;li&gt;In lib\cucumber\formatters\ansicolor.rb, comment out the first line that says "gem 'term-ansicolor'".  (I wasn't able to get ANSI color to work for the output from Cucumber.) &lt;/li&gt;

  &lt;li&gt;In lib\cucumber\tree\step.rb, find the "execute_in" method and then find the following code: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;method_line_pos = e.backtrace.index(method_line) 
    &lt;br /&gt;if method_line_pos 

    &lt;br /&gt;  strip_pos = method_line_pos - (Pending === e ? PENDING_ADJUSTMENT : REGULAR_ADJUSTMENT) 

    &lt;br /&gt;else 

    &lt;br /&gt;  # This happens with rails, because they screw up the backtrace 

    &lt;br /&gt;  # before we get here (injecting erb stactrace and such) 

    &lt;br /&gt;end 

    &lt;br /&gt;format_error(strip_pos, proc, e) &lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;and change it to: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;if e.backtrace 
    &lt;br /&gt;  method_line_pos = e.backtrace.index(method_line) 

    &lt;br /&gt;  if method_line_pos 

    &lt;br /&gt;    strip_pos = method_line_pos - (Pending === e ? PENDING_ADJUSTMENT : REGULAR_ADJUSTMENT) 

    &lt;br /&gt;  else 

    &lt;br /&gt;    # This happens with rails, because they screw up the backtrace 

    &lt;br /&gt;    # before we get here (injecting erb stactrace and such) 

    &lt;br /&gt;  end 

    &lt;br /&gt;  format_error(strip_pos, proc, e) 

    &lt;br /&gt;else 

    &lt;br /&gt;  e.extra_data = format_error2(proc, e) 

    &lt;br /&gt;  raise e 

    &lt;br /&gt;end          &lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In lib\spec\expectations\errors.rb, add two properties to the "ExpectationNotMetError" class as follows (this step and the last step are necessary because the file name and line are not included with the Exception message in IronRuby as they are in regular Ruby): &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;def extra_data=(value) 
    &lt;br /&gt;  @extra_data = value 

    &lt;br /&gt;end &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;def message 
    &lt;br /&gt;  to_s + "\n" + @extra_data 

    &lt;br /&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Testing .NET code&lt;/h3&gt;

&lt;p&gt;To complete the test, I created a simple C# source file to test called "Accent.cs" as follows:&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;namespace&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt; TestLibrary 
    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;{ 
    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Accent 
      &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;{ 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;readonly&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; _stateAbbreviation; &lt;/span&gt;

  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; Accent(&lt;span style="color: blue"&gt;string&lt;/span&gt; stateAbbreviation) 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;{ 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;            &lt;/span&gt;_stateAbbreviation = stateAbbreviation; 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;} &lt;/span&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; PronounceWord(&lt;span style="color: blue"&gt;string&lt;/span&gt; word) 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;{ 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;            &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (_stateAbbreviation == &lt;span style="color: #a31515"&gt;"MA"&lt;/span&gt;) 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;            &lt;/span&gt;{ 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                &lt;/span&gt;&lt;span style="color: blue"&gt;switch&lt;/span&gt; (word) 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                &lt;/span&gt;{ 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                    &lt;/span&gt;&lt;span style="color: blue"&gt;case&lt;/span&gt; &lt;span style="color: #a31515"&gt;"bar"&lt;/span&gt;: 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                        &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: #a31515"&gt;"bah"&lt;/span&gt;; 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                    &lt;/span&gt;&lt;span style="color: blue"&gt;case&lt;/span&gt; &lt;span style="color: #a31515"&gt;"dollar"&lt;/span&gt;: 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;       &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;                 &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: #a31515"&gt;"dolla"&lt;/span&gt;; 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;                &lt;/span&gt;} 

    &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;            &lt;/span&gt;} &lt;/span&gt;

  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;            &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; word; 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;        &lt;/span&gt;} 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;} 

  &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" new?;="new?;" courier="courier"&gt;} 
  &lt;p&gt;&lt;/p&gt;
&lt;/span&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;/p&gt;

&lt;p&gt;I compiled that source file into an assembly called "TestLibrary.dll" and copied it (and TestLibrary.pdb) to a new folder: C:\Projects\IronRuby\trunk\lib\lib.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;/p&gt;

&lt;p&gt;Next, I created a file called cucumber.yml in C:\Projects\IronRuby\trunk\lib with the following contents (copied from the "calculator" example provided in Cucumber):&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;code&gt;default: --format pretty features&lt;/code&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;I also created another file (also copied from the "calculator" example) called Rakefile with the following contents:&lt;/p&gt;

&lt;p&gt;$:.unshift(File.dirname(__FILE__) + '/../../lib') 
  &lt;br /&gt;require 'cucumber/rake/task' &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Cucumber::Rake::Task.new do |t| 
    &lt;br /&gt;  t.cucumber_opts = "--profile default" 

    &lt;br /&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;/p&gt;

&lt;p&gt;Next, I created a file called pronunciation.feature (a specification) in a new folder: C:\Projects\IronRuby\trunk\lib\features with the following contents:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Feature: Pronunciation 
    &lt;br /&gt;  In order to gain the trust of a customer 

    &lt;br /&gt;  As a sales representative 

    &lt;br /&gt;  I want to pronounce words in the dialect of the customer &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;  Scenario: Pronounce a word 
    &lt;br /&gt;    Given My client lives in MA 

    &lt;br /&gt;    When I pronounce bar 

    &lt;br /&gt;    Then the word should be pronounced bah &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;  Scenario: Pronounce a word 
    &lt;br /&gt;    Given My client lives in CA 

    &lt;br /&gt;    When I pronounce bar 

    &lt;br /&gt;    Then the word should be pronounced bar &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;  Scenario: Pronounce a word 
    &lt;br /&gt;    Given My client lives in MA 

    &lt;br /&gt;    When I pronounce dollar 

    &lt;br /&gt;    Then the word should be pronounced dolla &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;  Scenario: Pronounce a word 
    &lt;br /&gt;    Given My client lives in CA 

    &lt;br /&gt;    When I pronounce dollar 

    &lt;br /&gt;    Then the word should be pronounced dollar &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Next, I created a file called proncuation_steps.rb (defining the steps in the specification above) in a new folder: C:\Projects\IronRuby\trunk\lib\features\steps with the following contents:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require 'spec' 
    &lt;br /&gt;$:.unshift(File.dirname(__FILE__) + '/../../lib') 

    &lt;br /&gt;require 'mscorlib' 

    &lt;br /&gt;require 'TestLibrary' 

    &lt;br /&gt;

    &lt;br /&gt;Before do 

    &lt;br /&gt;end 

    &lt;br /&gt;

    &lt;br /&gt;After do 

    &lt;br /&gt;end 

    &lt;br /&gt;

    &lt;br /&gt;Given "My client lives in $state" do |state| 

    &lt;br /&gt;    @accent = TestLibrary::Accent.new state 

    &lt;br /&gt;end 

    &lt;br /&gt;

    &lt;br /&gt;When /I pronounce (\w+)/ do |word| 

    &lt;br /&gt;  @result = @accent.PronounceWord word 

    &lt;br /&gt;end 

    &lt;br /&gt;

    &lt;br /&gt;Then /the word should be pronounced (.*)/ do |result| 

    &lt;br /&gt;  @result.to_s.should == result.to_s 

    &lt;br /&gt;end

    &lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, I created two files in C:\Projects\IronRuby\trunk\build\debug. The first of them is icuc.rb, which contains the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require 'cucumber' 
    &lt;br /&gt;require 'cucumber/cli' 

    &lt;br /&gt;

    &lt;br /&gt;Cucumber::CLI.execute&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The second file is icuc.bat, which contains the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@echo off 
    &lt;br /&gt;set IRONRUBY=c:\Projects\IronRuby\trunk 

    &lt;br /&gt;pushd %IRONRUBY%\lib 

    &lt;br /&gt;%IRONRUBY%\build\Debug\ir %IRONRUBY%\build\Debug\icuc.rb 

    &lt;br /&gt;popd 

    &lt;br /&gt;set IRONRUBY=&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These two files are the equivalent of the "cucumber" and "cucumber.cmd" files in C:\ruby\bin.  You can now type "icuc" at a command prompt and it will run the Cucumber test you just created, which should pass!  I chose the name "icuc" so that it wouldn't conflict with the "cucumber" command in regular Ruby.  Happy testing, er... I mean verifying! ;-)&lt;/p&gt;

&lt;p&gt;If you have any trouble getting this to work for you, or if you know of a better way to do it, please leave a comment!  I know this method is less than ideal, so I'm hoping one of you can help me improve it. :-)&lt;/p&gt;&lt;img src="http://patrickgannon-net.access.secure-ssl-servers.biz/aggbug/7.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/7.aspx</wfw:comment>
        <slash:comments>10</slash:comments>
        <wfw:commentRss>http://patrickgannon-net.access.secure-ssl-servers.biz/comments/commentRss/7.aspx</wfw:commentRss>
        <trackback:ping>http://patrickgannon-net.access.secure-ssl-servers.biz/services/trackbacks/7.aspx</trackback:ping>
    </entry>
</feed>