<rss version="2.0" 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:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Nuri Halperin</title>
        <link>http://geekswithblogs.net/nuri/Default.aspx</link>
        <description>blog</description>
        <language>en-US</language>
        <copyright>Nuri Halperin</copyright>
        <managingEditor>nuri@brandx.net</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <image>
            <title>Nuri Halperin</title>
            <url>http://geekswithblogs.net/images/RSS2Image.gif</url>
            <link>http://geekswithblogs.net/nuri/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>Between - Extension method to shorten notation</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/10/17/between---extension-method-to-shorten-notation.aspx</link>
            <description>&lt;p&gt;Sometimes I just write code. And sometimes I clean up my code. Most of the times, I focus on the meat of the methods, hacking away at verbose or lengthy flows, re-factoring out common code, trying to untangle overly complex logic etc. &lt;br /&gt;&lt;br /&gt;Recently, I noticed that many of the conditional terms I write span very long lines and are a bit cumbersome to read. The reason for that is that many of the variable names are long, or the properties or both and that often the comparison is on a property of an object or member of a collection etc. &lt;br /&gt;&lt;br /&gt;So for instance:&lt;/p&gt; &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (summerCatalog.Products[0].ProductCategories[0].ParentCategoryID &amp;gt;= 1 &amp;amp;&amp;amp; summerCatalog.Products[0].ProductCategories[0].ParentCategoryID &amp;lt;= 4)
{ 
&lt;span style="color: #008000"&gt;//...&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;Can become quite long. &lt;br /&gt;Long is not easy to read. &lt;br /&gt;Long is not easy to maintain. &lt;br /&gt;Long is not easy to think through. &lt;br /&gt;&lt;br /&gt;What I really wanted to say is if [value] is between [a] and [b].&lt;/p&gt;
&lt;p&gt;Of course, one could say "lets just make the variable names shorter". But that flies in the face of self explanatory plain naming. So abbreviating for the sake of short-lineliness (New word! You heard it her first!) is out. &lt;br /&gt;&lt;br /&gt;Well, this is just screaming "EXTENSION METHODS" doesn't it? &lt;br /&gt;&lt;br /&gt;Here we go then:&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// Returns whether the value is between the 2 specified boundaries.&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;param name="value"&amp;gt;The value to compare&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;param name="minValueInclusive"&amp;gt;The min value (inclusive).&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;param name="maxValueInclusive"&amp;gt;The max value (inclusive).&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span style="color: #008000"&gt;/// &amp;lt;returns&amp;gt;True if the value is equal to or between the boundaries; False otherwise.&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Between&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; T &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, T minValueInclusive, T maxValueInclusive) &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; T : IComparable&amp;lt;T&amp;gt;
{
    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (minValueInclusive.CompareTo(maxValueInclusive) &amp;gt; 0)
    {
        &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentException(&lt;span style="color: #006080"&gt;"minimum value must not be greater than maximum value"&lt;/span&gt;);
    }
    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.CompareTo(minValueInclusive) &amp;gt;= 0 &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.CompareTo(maxValueInclusive) &amp;lt;= 0);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Between function takes any object which supports IComparable&amp;lt;T&amp;gt; and performs syntactic sugar comparison with the inclusive min and max values. &lt;br /&gt;What's more, it adds a basic sanity check for the comparison. How many times do I do that sanity check in my normal code (!)? &lt;br /&gt;&lt;br /&gt;Now the conditional is &lt;br /&gt;&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (summerCatalog.Products[0].ProductCategories[0].ParentCategoryID.Between(1, 4)) 
{
&lt;span style="color: #008000"&gt;///...&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;At least I don't have to refactor this in my brain while reading.&lt;/p&gt;
&lt;p&gt;Sure, you might say, but you could have just de-referenced the deep value and then have a shorter conditional, like so:&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;Category category = summerCatalog.Products[0].ProductCategories[0];
&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (category.ParentCategoryID &amp;gt;= 1 &amp;amp;&amp;amp; category.ParentCategoryID &amp;lt;= 4)
{
    &lt;span style="color: #008000"&gt;//...&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;Yes - of course - but it adds a line of code, places the burden of reading the very common idiom ( x &amp;gt;= a &amp;amp;&amp;amp; x &amp;lt;= b) on me, and I constantly stumble on the lest-than-or-equal vs. less-than and it doesn't check for my boundaries being inadvertently swapped. &lt;br /&gt;&lt;br /&gt;So there you have it. A simple extension cuts down your lines of code, makes long text shorter and saves lives. Which begs the question: is this already part of the language - and should it be? &lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135510"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135510" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/135510.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/10/17/between---extension-method-to-shorten-notation.aspx</guid>
            <pubDate>Sat, 17 Oct 2009 05:49:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/135510.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/10/17/between---extension-method-to-shorten-notation.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/135510.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/135510.aspx</trackback:ping>
        </item>
        <item>
            <title>Unit Testing and approval tests</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/08/08/unit-testing-and-approval-tests.aspx</link>
            <description>&lt;p&gt;It's been years now that unit testing frameworks and tools have grabbed our attention, made their way into our favorite IDE and sparked yet another wave of seemingly endless "my framework is better than yours" wars. And then there are the principal wars of whether TDD is better than Test After Development. And most excitingly the automated testing tools etc. Oh, and let's not forget mocks! So we have all the tools we need – right? Well, kind of, no.&lt;/p&gt;  &lt;p&gt;I recently attended a talk by Llewellyn Falco and Woody Zuill the other day, and they used a little library called Approval Tests (&lt;a href="http://approvaltests.com/" target="_blank"&gt;http://approvaltests.com/&lt;/a&gt;). I immediately fell in love with the concept and the price ($0). Llewellyn is one of the two developers of the product, hosted on &lt;a href="http://sourceforge.net/projects/approvaltests/" target="_blank"&gt;http://sourceforge.net/projects/approvaltests/&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;What does it do that years of frameworks don't?&lt;/p&gt;  &lt;p&gt;For me, a major nuisance is that you have a piece of code, and that piece of code produces a result (object, state – call it what you will). That result is commonly named "actual" in Visual Studio unit tests. The developer must then assert against that result to ensure that the code ran properly. In theory, unit tests are supposed to be small and only test one thing. In reality, functions which return complex objects rarely can be asserted with one assert. You'd typically find yourself asserting several properties or testing some behavior of the actual value. In corporate scenario, the unit tests might morph into some degree of integration tests and objects become more complex, requiring a slew of assert.this and assert.that().&lt;/p&gt;  &lt;p&gt;What if you could just run the code, inspect the value returned, and – if it satisfies the requirements – set "that value" to be the comparison for all future runs? Wouldn't that be nice? Good news: Approval Tests does just that. So now, instead of writing so many asserts against your returned value, you just call ApprovalTests.Approve() and the captured state is compared against your current runtime. Neat huh?&lt;/p&gt;  &lt;p&gt;But wait, there's more! What if your requirements are regarding a windows form, or a control? how do you write a unit test that asserts against a form? The answer is simple and genius: Capture the form as an image, and compare the image produced by your approved form (after you have carefully compared it to the form given to you by marketing – right?) and compare it to each subsequent run. ApprovalTests simply does a byte by byte comparison of the resultant picture of the form and tells you if it matches what you approved.&lt;/p&gt;  &lt;p&gt;Let's break down the steps for installation:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Add a reference to the ApprovalTests.dll assembly. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Yeah,it's that simple.&lt;/p&gt;  &lt;p&gt;Ok. Let's break down the steps for adding an approval to your unit test&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Write your unit test (arrange, act – no asserts) as usual. &lt;/li&gt;    &lt;li&gt;Add a call to Approve() &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Yeah, it's that simple.&lt;/p&gt;  &lt;p&gt;How do you tell it that the value received is "the right one"? Upon first run, the Approve() call will always fail. Why? Because it has no stored approved value to compare the actual it received against. When it fails, it will print out a message (console or test report – depends on your unit test runner). That message will contain a path for the file that it received, complaining about a lack of approved file. The value captured from that run (and any subsequent run) is stored in a file named something like "{your unit test file path}\{your method}.received.xyz". If you like the result of the run -the image matches what the form should look like, or the text value is what your object should contain etc – then you can rename it to "{your unit test file path}\{your method}.approved.xyz". You should check the approved file into your source control. After all, it's content constitutes the basis of the assertion in your unit test!&lt;/p&gt;  &lt;p&gt;Consider the very simple unit test code:&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;   &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; [Test]&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DateTime_Constructor_YMDSetDate()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             DateTime actual;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             actual = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DateTime(2038, 4, 1);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             Approvals.Approve(actual.ToString());&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The function under test here is the constructor for System.DateTime which takes 3 parameters – month day and year. Upon first run, the test will fail with a message resembling&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;"&lt;em&gt;TestCase 'MyProject.Tests.DateTimeTest.DateTime_Constructor_YMDSetDate' 
      &lt;br /&gt;failed: ApprovalTests.Core.Exceptions.ApprovalMissingException : Failed Approval: Approval File "C:\….\MyProject\DateTimeTest.DateTime_Constructor_YMDSetDate.approved.txt" Not Found."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's because this file was never created – it's your first run. Using the standard approver, this file will actually now be created but will be empty. In that same directory you will find a file named {…}.received.txt. This is the capture from this run. You can open the received value file, and inspect the text to ensure that the value returned matches your expected value. If it does, simply rename that file to .approved.text or copy it's content over and run the test again. This time, the Approve() method should succeed. If at any point in the future the method under test returns a different value, the approval will fail. If at any point in the future the specs change, you will need to re-capture a correct behavior and save it.&lt;/p&gt;

&lt;p&gt;How do you easily compare the values from the last run and the saved approved value? The approved file is going to be a text file for string approvals, and an image file for WinForm approvals. As it turns out, you can instruct Approval Tests to launch a diff program with the 2 files (received, approved) automatically upon failure, or just open the received file upon failure or silently just fail the unit test. To control that behavior, you use a special attribute&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; [TestFixture]&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; [UseReporter(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(DiffReporter))]&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ObjectWriterTest&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The UserReporterAttribute allows you to specify one of 3 included reporters&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;DiffReporter – which opens tortoisediff for diffing the received and approved files if the comparison fails. &lt;/li&gt;

  &lt;li&gt;OpenReceivedFileReporter – which launches the received file using the application registered to it's extension on your system if the comparison fails. &lt;/li&gt;

  &lt;li&gt;QuietReporter – which does not launch any program but only fails the unit test if the comparison fails. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When your have a CI server and run unit tests as part of your builds, you probably want to use the quiet reporter. For interactive sessions, one of the first 2 will probably be more suitable.&lt;/p&gt;

&lt;p&gt;How are value comparisons performed? Under the standard built in methods, a file is written out and compared to byte by byte. If you wish to modify this or any behavior, you can implement your own approver or file writer or reporter by implementing simple interfaces. I ended up adding a general use object writer so that I can approve arbitrary objects. The effort was fairly painless and straightforward.&lt;/p&gt;

&lt;p&gt;I did have to read the code to get the concept. If only my time machine worked: I could have read my own blog and saved myself 20 minutes. Yeah, right.&lt;/p&gt;

&lt;p&gt;The project has some bells and whistles – plug ins for a few IDE's and there's a version for Java and Ruby. I have not reviewed these versions.&lt;/p&gt;

&lt;p&gt;There you have it folks- a shiny new tool under your belt. I can see this saving my hours of mindless typing of Assert.* calls and I can go home early. Yeah, right.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133976"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133976" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/133976.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/08/08/unit-testing-and-approval-tests.aspx</guid>
            <pubDate>Sat, 08 Aug 2009 06:13:19 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/133976.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/08/08/unit-testing-and-approval-tests.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/133976.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/133976.aspx</trackback:ping>
        </item>
        <item>
            <title>MVC Radio Button List</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-radio-button-list.aspx</link>
            <description>&lt;p&gt;As predicted, I came around to using some radio  buttons. As you might guess by now, I didn't like the HTML or the implementation in the current MVC release. As you may expect, I wrote my own :-)&lt;/p&gt;  &lt;p&gt;The implementation is fairly simple and straightforward. It extends System.Web.MVC.ViewPage, takes a list of objects, allows for selection of one of the radio buttons, supports orientation and supports selection of both the value the radio button submits and the display string for that item independently.&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;   &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Linq.Expressions;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HtmlHelpers&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ShowRadioButtonList&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ViewPage page, IList&amp;lt;T&amp;gt; list, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name, Expression&amp;lt;Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; valueProperty, Expression&amp;lt;Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; displayProperty, System.Web.UI.WebControls.Orientation orientation)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         page.ShowRadioButtonList(list, name, valueProperty, displayProperty, &lt;span style="color: #006080"&gt;"3"&lt;/span&gt;, orientation);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ShowRadioButtonList&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ViewPage page, IList&amp;lt;T&amp;gt; list, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name, Expression&amp;lt;Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; valueProperty, Expression&amp;lt;Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; displayProperty, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; selectedValue, System.Web.UI.WebControls.Orientation orientation)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         HtmlTextWriter writer = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HtmlTextWriter(page.Response.Output);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (writer != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt; valueGetter = valueProperty.Compile();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             Func&amp;lt;T, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt; displayStringGetter = displayProperty.Compile();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; list.Count; i++)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;                 T row = list[i];&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; = valueGetter(row).ToString();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                 writer.AddAttribute(HtmlTextWriterAttribute.Type, &lt;span style="color: #006080"&gt;"radio"&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                 writer.AddAttribute(HtmlTextWriterAttribute.Id, name + &lt;span style="color: #006080"&gt;"_"&lt;/span&gt; + i);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                 writer.AddAttribute(HtmlTextWriterAttribute.Name, name, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;                 writer.AddAttribute(HtmlTextWriterAttribute.Value, &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt; == selectedValue)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                 {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;                     writer.AddAttribute(HtmlTextWriterAttribute.Checked,&lt;span style="color: #006080"&gt;"checked"&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;                 }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;                 writer.RenderBeginTag(HtmlTextWriterTag.Input);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                 writer.Write(displayStringGetter(row));&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;                 writer.RenderEndTag();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (orientation == System.Web.UI.WebControls.Orientation.Vertical)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;                 {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;                     writer.RenderBeginTag(HtmlTextWriterTag.Br);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;                     writer.RenderEndTag();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;                 }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  47:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This implementation uses the type Expression&amp;lt;Func&amp;lt;T,Object&amp;gt;&amp;gt; for the selection of the value and the display string. To invoke the helper, assuming you have a list of Product objects, Product being defined:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Product&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ProductID { get; set; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Title { get; set; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Description { get; set; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;decimal&lt;/span&gt; Price { get; set; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;You can now call the helper from your MVC View Page strongly typed with a model List&amp;lt;Product&amp;gt;:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;%@ Page Title=&lt;span style="color: #006080"&gt;""&lt;/span&gt; Language=&lt;span style="color: #006080"&gt;"C#"&lt;/span&gt; Inherits=&lt;span style="color: #006080"&gt;"System.Web.Mvc.ViewPage&amp;lt;List&amp;lt;Product&amp;gt;&amp;gt;"&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     MasterPageFile=&lt;span style="color: #006080"&gt;"~/Views/Shared/Site.Master"&lt;/span&gt; %&amp;gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;  &lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;invoked simply&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;% &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ShowRadioButtonList&amp;lt;Product&amp;gt;(Model, &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;                             &lt;span style="color: #006080"&gt;"productRadioButtonList"&lt;/span&gt;, &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;                             a =&amp;gt; a.ProductID, &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;                             d =&amp;gt; d.Title, &lt;span style="color: #006080"&gt;"4"&lt;/span&gt;, &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;                             Orientation.Horizontal); %&amp;gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This call will create a radio button for each product in the list (Model is a List&amp;lt;Product&amp;gt; because we strongly typed the page as such). The radio button will use the ProductID property for the value of the input, and the Title property as the displayed string. If one of the product Id's happens to be 4, that radio button will be selected in the group. The radio buttons will all be named "productRadioButtonList" but their ID will be appended an ordinal number  "productRadioButtonList_1","productRadioButtonList_2","productRadioButtonList_3" etc.&lt;/p&gt;

&lt;p&gt;There you have it: another day, another MVC control, another blog post.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133931"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133931" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/133931.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-radio-button-list.aspx</guid>
            <pubDate>Thu, 06 Aug 2009 00:29:29 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/133931.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-radio-button-list.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/133931.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/133931.aspx</trackback:ping>
        </item>
        <item>
            <title>MVC paged list</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-paged-list.aspx</link>
            <description>&lt;h2&gt;The need&lt;/h2&gt;  &lt;p&gt;As certain as the sun rising tomorrow, there will come the point where you will want to display a list or grid with paging. While many solutions exist, and many component developers are coming in with robust solutions, a simple and satisfactory solution can be created fairly easily.&lt;/p&gt;  &lt;h2&gt;Implementation&lt;/h2&gt;  &lt;p&gt;Why create a pager from scratch? Several reasons:&lt;/p&gt;  &lt;p&gt;1) You want to control the pager completely – display, style and all.&lt;/p&gt;  &lt;p&gt;2) You don't like the idea of JavaScript paging, which will load your hundreds of pages to the browser and do client side paging / grid&lt;/p&gt;  &lt;p&gt;3) You want to understand and control exactly how a page subset of record is fetched and take control of database or IO thrashing&lt;/p&gt;  &lt;p&gt;Of the quickly surveyed solutions out there, I found &lt;a href="http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/" target="_blank"&gt;this one&lt;/a&gt; simple and straightforward. Being small, straightforward and simple means also easy to maintain, extend or modify. Based on that solution, I've created my own pager which breaks into 2 class implementations and one usage guidance.&lt;/p&gt;  &lt;p&gt;The first class, is the PagedList class. The whole class is rather small and the only crux is doing correct math and ensuring the logic handles zero items returned. This class is responsible for taking a source list of all items (more on that below in the performance considerations) and presenting simple properties for HasNextPage, HasPreviousPage, TotalPages and CurrentPage. The implementation inherits from the generic List&amp;lt;T&amp;gt;, and so exposes and enumerator and the Count property. The constructor copies only the current page's worth of items into the instance though, so Count will return the number of items on the current page (0 to page size) therefore an additional property TotalItems is populated upon construction which exposes the total number of items in the underlying source. &lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;
&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Linq;

&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; BL.Models
{

    &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// Adapted from http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;typeparam name="T"&amp;gt;The type of item this list holds&amp;lt;/typeparam&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; PagedList&amp;lt;T&amp;gt; : List&amp;lt;T&amp;gt;, IPagedList
    {
        &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span style="color: #008000"&gt;/// Initializes a new instance of the &amp;lt;see cref="PagedList&amp;amp;lt;T&amp;amp;gt;"/&amp;gt; class.&lt;/span&gt;
        &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span style="color: #008000"&gt;/// &amp;lt;param name="source"&amp;gt;The source list of elements containing all elements to be paged over.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span style="color: #008000"&gt;/// &amp;lt;param name="currentPage"&amp;gt;The current page number (1 based).&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span style="color: #008000"&gt;/// &amp;lt;param name="pageSize"&amp;gt;Size of a page (number of items per page).&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; PagedList(IEnumerable&amp;lt;T&amp;gt; source, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; currentPage, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; itemsPerPage)
        {
            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.TotalItems = source.Count();
            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ItemsPerPage = itemsPerPage;
            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CurrentPage = Math.Min(Math.Max(1, currentPage), TotalPages);
            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.AddRange(source.Skip((&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CurrentPage - 1) * itemsPerPage).Take(itemsPerPage).ToList());
        }


        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CurrentPage {get ;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set;}

        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ItemsPerPage { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }

        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; HasPreviousPage { get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (CurrentPage &amp;gt; 1); } }

        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; HasNextPage { get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (CurrentPage * ItemsPerPage) &amp;lt; TotalItems; } }

        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; TotalPages { get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)Math.Ceiling((&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;)TotalItems / ItemsPerPage); } }

        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; TotalItems { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;PagedList implements the interface IPagedList, since a static class can not be generic, and the control renderer will need access to the PagedList's properties:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; BL.Models&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IPagedList&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CurrentPage { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; HasNextPage { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; HasPreviousPage { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ItemsPerPage { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; TotalItems { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; TotalPages { get; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The second class is more like a custom web control. Since this is MVC, we are driven to use a helper like implementation. My approach to developing HTML helpers for MVC is to create an extension method on the System.Web.MVC.ViewPage type. This allows the use of the well known and tested HtmlTextWriter to render the actual HTML rather than creating angled brackets in strings on the fly. I find this approach both more true to the form – rendering output to the output stream and not composing a string to be copied later – and safe: using compliant well tested constants and constructs rather than typing in HTML and hoping your syntax and understanding of the tag is correct.&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc;
&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI;

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HtmlHelpers
{
    &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// Shows a pager control - Creates a list of links that jump to each page&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="page"&amp;gt;The ViewPage instance this method executes on.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="pagedList"&amp;gt;A PagedList instance containing the data for the paged control&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="controllerName"&amp;gt;Name of the controller.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="actionName"&amp;gt;Name of the action on the controller.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ShowPagerControl(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ViewPage page, IPagedList pagedList, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; controllerName, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName)
    {
        HtmlTextWriter writer = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HtmlTextWriter(page.Response.Output);
        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (writer != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
        {
            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pageNum = 1; pageNum &amp;lt;= pagedList.TotalPages; pageNum++)
            {
                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pageNum != pagedList.CurrentPage)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, &lt;span style="color: #006080"&gt;"/"&lt;/span&gt; + controllerName + &lt;span style="color: #006080"&gt;"/"&lt;/span&gt; + actionName + &lt;span style="color: #006080"&gt;"/"&lt;/span&gt; + pageNum);
                    writer.AddAttribute(HtmlTextWriterAttribute.Alt, &lt;span style="color: #006080"&gt;"Page "&lt;/span&gt; + pageNum);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                }

                writer.AddAttribute(HtmlTextWriterAttribute.Class,
                                    pageNum == pagedList.CurrentPage ?
                                                        &lt;span style="color: #006080"&gt;"pageLinkCurrent"&lt;/span&gt; :
                                                        &lt;span style="color: #006080"&gt;"pageLink"&lt;/span&gt;);

                writer.RenderBeginTag(HtmlTextWriterTag.Span);
                writer.Write(pageNum);
                writer.RenderEndTag();

                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pageNum != pagedList.CurrentPage)
                {
                    writer.RenderEndTag();
                }
                writer.Write(&lt;span style="color: #006080"&gt;"&amp;amp;nbsp;"&lt;/span&gt;);
            }

            writer.Write(&lt;span style="color: #006080"&gt;"("&lt;/span&gt;);
            writer.Write(pagedList.TotalItems);
            writer.Write(&lt;span style="color: #006080"&gt;" items in all)"&lt;/span&gt;);
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The implementation creates a list of page numbers, with a link on each except for the current page. The link will be of the format "/{controller name}/{action name}/{page number}".&lt;/p&gt;

&lt;p&gt;I have added conditional style attribute to the link so that you can style the current page differently from the other pages easily. Since you have the code, you can extend the resultant HTML as you wish. You might want to have text indication of "no more pages" or some indication if the list is empty etc.&lt;/p&gt;

&lt;p&gt;Finally, you would want to make use of this shiny new widget. The steps are as follows&lt;/p&gt;

&lt;p&gt;1) In your controller, create an action which takes the page number as it's sole parameter. The action would then create a new instance of the PagedList, passing it the "full list" and the current page number from the parameter.&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Page(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; id)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            List&amp;lt;Product&amp;gt; products = CatalogService.ListOpenProducts();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            PagedList&amp;lt;Product&amp;gt; data = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PagedList&amp;lt;Product&amp;gt;(products, id, PAGE_SIZE);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(data);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;2) Change / create a view which takes the PagedList&amp;lt;your row type&amp;gt; as it's model. &lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;%@ Page Title=&lt;span style="color: #006080"&gt;""&lt;/span&gt; Language=&lt;span style="color: #006080"&gt;"C#"&lt;/span&gt; MasterPageFile=&lt;span style="color: #006080"&gt;"~/Views/Shared/Site.Master"&lt;/span&gt; 
Inherits=&lt;span style="color: #006080"&gt;"System.Web.Mvc.ViewPage&amp;lt;BL.Models.PagedList&amp;lt;Product&amp;gt;&amp;gt;"&lt;/span&gt; %&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;3) Place a call to the extension method to display the pager anywhere in your view (multiple placement allowed – you can put one on top and one on the bottom etc). Recall that the method ShowPagerControl() extends  ViewPage, so the keyword this should show your intellisence for the method. If you chose a more complex model (MVVM ViewModel containing more data than just the paged list) then you would use Model.{paged list property name}. The use of the view as a bag of random data conjured up by string names should IMHO be universally abandoned and eliminated.&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 43px; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;% &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ShowPagerControl(Model, &lt;span style="color: #006080"&gt;"Bids"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Page"&lt;/span&gt;); %&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;Considerations&lt;/h2&gt;

&lt;h3&gt;Take != load all + scroll&lt;/h3&gt;

&lt;p&gt;The PagedList implementation takes an IEnumerable&amp;lt;T&amp;gt; as it's source data. Internally, it uses Linq syntax which would seem to require all items be loaded, and then skip the first N pages and take the next {page size} worth of items. If your underlying list of items is a huge DB call, you will find that troubling. What you might consider then will be to use deferred loading. Extend the Linq IQueryable&amp;lt;T&amp;gt; or ObjectQuery&amp;lt;T&amp;gt; and let the ORM of your choice do the paging in the database. If your ORM is eager loader, you will need to implement custom partial record loading and paging at the data source level. If it can defer loading you will be in better shape.&lt;/p&gt;

&lt;p&gt;Conversely, you might want to actually eager-load all records at the first shot. This will provide you with 2 benefits: cachability and coherency. Loading all items into memory incurs one DB call overhead and the IO required for all records. If you load each page at a time, you would incur {page count} * page clicks DB call overheads which might exceed the former if users scroll often back and forth. Once you load the whole list, you can cache it in memory and expire it based on data change events. If you have the base list in memory, access to it incurs no more IO regardless of pager clicks. Another phenomena caching gets around is coherency problems. If you page ad the DB level and an item is inserted or deleted, the end user experiences skips or stutter items. A skip is when a user clicks from page 1 to 2 an item which was to be on page 2 now is in the range of page 1 because an item on page 1 was deleted. Going to page 2 skips this item, and paging back should reveal it but would be surprising to the user (because she just came from page 1 and it wasn't there before) creating the appearnace of a skipped / missed item. A stutter is the reverse situation: user clicks from page 1 to 2, and an item from page 1 appears again on page 2. This happens when an item was added and "pushed" the repeat item into page 2 because of it's sorting order. This appears to the user as a malfunction and may infuriate some enough to call customer service (alas, advising customers to adjust their medication does not actually calm them down). A solution to coherence is to cache the result list for each user, expiring the cache actively when navigating away or running a different query.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The code above and variations of it are fairly easy to create. If your favorite web control vendor has not solved this for you, if you want to take full control of your paging of if you are just naturally curious – it's a great way to add paging to your MVC application.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133925"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133925" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/133925.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-paged-list.aspx</guid>
            <pubDate>Wed, 05 Aug 2009 19:16:34 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/133925.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-paged-list.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/133925.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/133925.aspx</trackback:ping>
        </item>
        <item>
            <title>MVC + ASP.Net template control and user control</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/07/24/mvc--asp.net-template-control-and-user-control.aspx</link>
            <description>&lt;p&gt;Seeing that I can use a DataBoundControl such as DataList, and binding it to a source control is achievable – what next?&lt;/p&gt;  &lt;p&gt;Data bound controls contain various templates. The usual suspects are the item template and alternating template (for a repeating object, with possible varied style), the header and the footer templates (for enclosing HTML pre/post wrap or header / footer effects).&lt;/p&gt;  &lt;p&gt;Under MVC, all events are out the window. So we're not concerned at all with event hookup. We might want to provide the various "modes" of display (Edit, Create, Delete etc) which align well with CRUD command structure and may map to MVC quite naturally. But for starters, my project's requirements simply required styling of the repeating item to be easily controlled.&lt;/p&gt;  &lt;p&gt;So rather than inline HTML in the &amp;lt;ItemTemplate&amp;gt; tag, I wanted to use a user control (ASCX). This allows my to style the item once and re-use it in pop-ups or other areas of the site, not just the data list view.&lt;/p&gt;  &lt;p&gt;The question becomes then – how do I pass data "down" to the user control? The answer turned out to be to easy – you don't have to do anything! That's right, the containing DataList gets bound to data. The user control then can pluck fields from the "data row" (each item in the bound list of the parent) by using the syntax Eval("{some property}")&lt;/p&gt;  &lt;p&gt;So the steps are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create your user control (MiniItem.ascx) &lt;/li&gt;    &lt;li&gt;Register the user control in the hosting ASPX page &lt;/li&gt;    &lt;li&gt;Include the user control in the item template of your data bound control &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt; The user control is an .ascx file, but change it to just inherit from System.Web.UI.UserControl. This is MVC so code behind is left behind..&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;%@ Control Language=&lt;span style="color: #006080"&gt;"C#"&lt;/span&gt; Inherits=&lt;span style="color: #006080"&gt;"System.Web.UI.UserControl"&lt;/span&gt; %&amp;gt;
&amp;lt;fieldset&amp;gt;
    &amp;lt;legend&amp;gt;Oh Goodie!&amp;lt;/legend&amp;gt;
    &amp;lt;p&amp;gt;
        Product ID:
        &amp;lt;%#Eval(&lt;span style="color: #006080"&gt;"ProductID"&lt;/span&gt;) %&amp;gt;
    &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;
        Title:
        &amp;lt;%#Eval(&lt;span style="color: #006080"&gt;"Title"&lt;/span&gt;) %&amp;gt;
    &amp;lt;/p&amp;gt;
    &amp;lt;img src=&lt;span style="color: #006080"&gt;'/Content/ProductImages/&amp;lt;%#Eval("ImagePath") %&amp;gt;'&lt;/span&gt; alt=&lt;span style="color: #006080"&gt;'Image Path'&lt;/span&gt; /&amp;gt;
    &amp;lt;p&amp;gt;
        Description:
        &amp;lt;%#Eval(&lt;span style="color: #006080"&gt;"Description"&lt;/span&gt;) %&amp;gt;
    &amp;lt;/p&amp;gt;
&amp;lt;/fieldset&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Your host ASPX file will need to register your control type in order to use it, so up at the top you place:&lt;/p&gt;

&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;%@ Register Src=&lt;span style="color: #006080"&gt;"MiniItem.ascx"&lt;/span&gt; TagName=&lt;span style="color: #006080"&gt;"MiniItem"&lt;/span&gt; TagPrefix=&lt;span style="color: #006080"&gt;"uc1"&lt;/span&gt; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Now you can use the user control simply by adding it to the ItemTemplate tag:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;asp:DataList runat=&lt;span style="color: #006080"&gt;"server"&lt;/span&gt; ID=&lt;span style="color: #006080"&gt;"dataList"&lt;/span&gt; RepeatColumns=&lt;span style="color: #006080"&gt;"4"&lt;/span&gt; RepeatDirection=&lt;span style="color: #006080"&gt;"Horizontal"&lt;/span&gt;&amp;gt;
    &amp;lt;ItemTemplate&amp;gt;
        &amp;lt;uc1:MiniItem ID=&lt;span style="color: #006080"&gt;"MiniItem1"&lt;/span&gt; runat=&lt;span style="color: #006080"&gt;"server"&lt;/span&gt; /&amp;gt;
    &amp;lt;/ItemTemplate&amp;gt;
&amp;lt;/asp:DataList&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There you have it. You can use the good concepts of ASPX and the controls and visual components you are familiar with. While HTML helpers and fluent interface libraries are popping up, some find it more convenient and easy to use the "old" familiar ASPX controls. There are some good reasons to learn new things and try new framework or software paradigms. However, we can also leverage many of the successful declarative features of ASPX as a templating engine to achieve rapid development and modular UI.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133700"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133700" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/133700.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/07/24/mvc--asp.net-template-control-and-user-control.aspx</guid>
            <pubDate>Sat, 25 Jul 2009 02:37:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/133700.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/07/24/mvc--asp.net-template-control-and-user-control.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/133700.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/133700.aspx</trackback:ping>
        </item>
        <item>
            <title>MVC, helpers and classic ASP.NET data bound controls &amp;ndash; Better Together</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/07/07/mvc-helpers-and-classic-asp.net-data-bound-controls-ndash-better.aspx</link>
            <description>&lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:71b6c970-1adf-433e-9d66-1d3848c7b1a6" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/MVC" rel="tag"&gt;MVC&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP.NET" rel="tag"&gt;ASP.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Extension+Methods" rel="tag"&gt;Extension Methods&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Html+Helper" rel="tag"&gt;Html Helper&lt;/a&gt;&lt;/div&gt;  &lt;p&gt;A lot of hype around MVC these days. So, of course, yours truly is working on some project utilizing MVC. While brushing the dust off my raw HTML tag memory and designing the obvious: lists, grids, repeated item displays and the such, I thought "why not use the asp.net controls instead?"&lt;/p&gt;  &lt;p&gt;For one, most of the ASP.NET data bound controls have a rich site of event post backs to hook up. MVC says: no dice! You can't rely on the event dispatch loop of asp.net. In fact, this is the whole point of going MVC – to create a simple, well separated delineation between the presentation and the BL. If you have all these states and post back logic pieces all in the code behind you really have a tightly coupled application.&lt;/p&gt;  &lt;p&gt;What *is* available though, is the rendering of most controls. So instead of "for each" and "if" statements sprinkled in the "presentation" template, you can actually just use the plain old asp.net controls declaratively. I put "presentation" in quotation marks because the more code (branching is code!) you have in the View, the more brittle it becomes, the more tightly coupled to BL it is and the less testable it is. &lt;/p&gt;  &lt;p&gt;The main advantages I find in using the old controls is that:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Familiarity – My developers know them already &lt;/li&gt;    &lt;li&gt;Rich – Theming, localization behavior and layout aspects built in and available &lt;/li&gt;    &lt;li&gt;Well tested – These controls have been around a while, and are generally well behaved &lt;/li&gt;    &lt;li&gt;Modular – The controls isolate the presentation of a particular element and divorce it from the surrounding. In particular, it avoids issues of nesting and other inline logic in the presentation layer. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The main issue to overcome in a DataBoundControl is that with no code behind, how do you specify the data source declaratively? How do you do so with minimum code and maximum flexibility?&lt;/p&gt;  &lt;p&gt;One solution is to use a data source object. Yes, they work. In most scenarios you can use them as you did before, but you must note that hooking up events (OnSelecting, OnSelected and the such) would again be challenging to do declaratively.&lt;/p&gt;  &lt;p&gt;My approach for my project was to create an extension method for &lt;/p&gt;  &lt;p&gt;DataBoundControl has a property "DataSource", to which you assign an object that will be data bound. The most permissive base object System.Object, so we simply create an extension method:&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI.WebControls;

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DataboundControlExtensions
{
    &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// Extends &amp;lt;typeparamref name="System.Object"/&amp;gt; to bind it to a &amp;lt;typeparamref name="System.Web.UI.WebControls.DataList"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="data"&amp;gt;The data source object to bind.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="control"&amp;gt;The control to bind the data source object to.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; BindTo(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; data, DataList control)
    {
        control.DataSource = data;
        control.DataBind();
    }

    &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// Extends &amp;lt;typeparamref name="System.Object"/&amp;gt; to bind it to a &amp;lt;typeparamref name="System.Web.UI.WebControls.ListView"/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="data"&amp;gt;The data source object to bind.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;param name="control"&amp;gt;The control to bind the data source object to.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; BindTo(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; data, ListView control)
    {
        control.DataSource = data;
        control.DataBind();
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note that the control is passed in as the target and is strongly typed. As it turns out, you get a runtime error if you attempt to specify the control parameter typed as DataBoundControl – the base class for all data bound controls. In other words, this doesn't work:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; BindTo(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; data, DataBoundControl control) &lt;span style="color: #008000"&gt;// Runtime error!&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With the extension included in my project, I can now add the control and  bind it in one code line:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;lt;% Model.BindTo(dataList); %&amp;gt;
&amp;lt;asp:DataList runat=&lt;span style="color: #006080"&gt;"server"&lt;/span&gt; ID=&lt;span style="color: #006080"&gt;"dataList"&lt;/span&gt; RepeatColumns=&lt;span style="color: #006080"&gt;"2"&lt;/span&gt; RepeatDirection=&lt;span style="color: #006080"&gt;"Horizontal"&lt;/span&gt;&amp;gt;
    &amp;lt;ItemTemplate&amp;gt;
        &amp;lt;fieldset&amp;gt;
            &amp;lt;legend&amp;gt;
                &amp;lt;%# Eval(&lt;span style="color: #006080"&gt;"ID"&lt;/span&gt;)%&amp;gt;&amp;lt;/legend&amp;gt;
            &amp;lt;p&amp;gt;
                Title:
                &amp;lt;%#Eval(&lt;span style="color: #006080"&gt;"Title"&lt;/span&gt;) %&amp;gt;
            &amp;lt;/p&amp;gt;
            &amp;lt;a href=&lt;span style="color: #006080"&gt;'&amp;lt;%#Eval("ImagePath") %&amp;gt;'&lt;/span&gt;&amp;gt;
                &amp;lt;img src=&lt;span style="color: #006080"&gt;'&amp;lt;%#Eval("ThumbPath") %&amp;gt;'&lt;/span&gt;  height=&lt;span style="color: #006080"&gt;"64"&lt;/span&gt; width=&lt;span style="color: #006080"&gt;"48"&lt;/span&gt; alt=&lt;span style="color: #006080"&gt;"pic"&lt;/span&gt;/&amp;gt;&amp;lt;/a&amp;gt;
            &amp;lt;p&amp;gt;
                Description:
                &amp;lt;%#Eval(&lt;span style="color: #006080"&gt;"Description"&lt;/span&gt;) %&amp;gt;
            &amp;lt;/p&amp;gt;
        &amp;lt;/fieldset&amp;gt;
    &amp;lt;/ItemTemplate&amp;gt;
&amp;lt;/asp:DataList&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is not as clean as completely declarative binding, but is much cleaner than having loop and branch constructs all over your view. &lt;/p&gt;

&lt;p&gt;Most of you would note that the current MVC release includes HTML helpers. The Futures release is promising several more HTML helpers, which would provide with single line calls that would render lists, and other data bound presentation we are accustomed to. The reasons I didn't use the futures HTML helper methods are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The futures were not in release yet at time &lt;/li&gt;

  &lt;li&gt;I don't love the mode in which the HTML helpers work &lt;/li&gt;

  &lt;li&gt;The HTML helpers are not as rich as the asp.net components &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The reason I don't love the HTML helpers is simple: they are string valued functions. As string valued functions, they must, internally generate strings and throw away memory. Even when you use StringBuilder, the repetitive appendage of strings creates discarded buffers in the underlying byte array. Asp.Net controls, on the other hand, have access to the underlying output stream via a TextWriter. This means that the appended string snippets do not create intermediary buffers but rather get copied more efficiently to the actual byte stream that would be shipped to the browser.&lt;/p&gt;

&lt;p&gt;So if I need to add an HTML helper to MVC what I do is write an extension method that extends System.Web.MVC.ViewPage, like so&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc;
&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.UI;

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HelloKittyHelper
{
    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Meow(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ViewPage page, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; text)
    {
        HtmlTextWriter writer = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HtmlTextWriter(page.Response.Output);
        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (writer != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Pre);
            writer.Write(KITTY_ASCII);
            writer.Write(text);
            writer.RenderEndTag();
        }
    }
    &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// ASCII art of a kitty - source unknown.&lt;/span&gt;
    &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; KITTY_ASCII = &lt;span style="color: #006080"&gt;@"
  .-. __ _ .-.
  |  `  / \  |
  /     '.()--\
 |         '._/
_| O   _   O |_
=\    '-'    /=
  '-._____.-'
  /`/\___/\`\
 /\/o     o\/\
(_|         |_)
  |____,____|
  (____|____)
"&lt;/span&gt;;
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then pass it the data from the Model or anything you like from the view:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
  &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="background-color: #ffff00"&gt;&amp;lt;%&lt;/span&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt;  &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Meow(&lt;span style="color: #006080"&gt;"purrr.. meow"&lt;/span&gt;);  &lt;/pre&gt;&lt;span style="background-color: #ffff00"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With the ambient objects in the page, I just extend "this", and internally utilize the HtmlTextWriter to write directly to the stream – no intermediary StringBuilder and hopefully less wasted immutable objects. The other advantage is that HtmlTextWriter can do things like begin/end tag tracking, add attributes and encode HTML as necessary. Leveraging existing well tested framework again, reducing costs of testing and education to deliver value early and often.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In conclusion, we can use the new MVC concepts and remain true to the separation of view and logic by leveraging existing components and developing minimal custom extensions that help us avoid the pitfalls of "presentation logic".&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133315"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133315" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/133315.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/07/07/mvc-helpers-and-classic-asp.net-data-bound-controls-ndash-better.aspx</guid>
            <pubDate>Wed, 08 Jul 2009 01:14:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/133315.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/07/07/mvc-helpers-and-classic-asp.net-data-bound-controls-ndash-better.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/133315.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/133315.aspx</trackback:ping>
        </item>
        <item>
            <title>Localize your MVC with ease.</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/06/07/localize-your-mvc-with-ease-again.aspx</link>
            <description>&lt;p&gt;MVC seems all the rage these days. And while there are many good things it brings to the table, it seams it takes us a step back in terms of I18N.&lt;/p&gt;  &lt;p&gt;For instance, if you want to use the special aspx attribute meta:resourceKey="foo", you won't always be able to do so.&lt;/p&gt;  &lt;p&gt;The following would work fine:&lt;/p&gt;  &lt;div&gt;   &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;asp:Label runat=&lt;span style="color: #006080"&gt;"server"&lt;/span&gt; ID=&lt;span style="color: #006080"&gt;"_QueryPrompt"&lt;/span&gt; Text=&lt;span style="color: #006080"&gt;"Enter Query"&lt;/span&gt; meta:resourcekey=&lt;span style="color: #006080"&gt;"_QueryPrompt"&lt;/span&gt; /&amp;gt;&amp;amp;nbsp;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;But we're out of luck with buttons:&lt;/p&gt;

&lt;div&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;asp:Button runat=&lt;span style="color: #006080"&gt;"server"&lt;/span&gt; ID=&lt;span style="color: #006080"&gt;"btn"&lt;/span&gt; Text=&lt;span style="color: #006080"&gt;"Run"&lt;/span&gt; meta:resourcekey=&lt;span style="color: #006080"&gt;"_SubmitQuery"&lt;/span&gt; /&amp;gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;At runtime, you will get an exception explaining you need a FORM with a runat="Server". Ugh.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;After some spelunking I came across &lt;a href="http://blog.eworldui.net/post/2008/05/ASPNET-MVC---Localization.aspx" target="_blank"&gt;this discussion&lt;/a&gt;, which basically suggests creating an extension to the System.Web.Mvc.HtmlHelper class. The discussion is thick with issues, specifically that if a UserControl is used, finding it's path in order to get to it's local resource requires all manners of digging around compilation and application with fairly extensive branching and parsing. Ultimately, the extension is complicated by attempting to combine both a resource retrieval, fallback to global from local resource and formatted template substitution in one. A good helper – if the kinks are worked out.&lt;/p&gt;

&lt;p&gt;So I wrote my own syntactic sugar to do the same:&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 232px; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Localize(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; System.Web.UI.UserControl control, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resourceKey, &lt;span style="color: #0000ff"&gt;params&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resource = (HttpContext.GetLocalResourceObject(control.AppRelativeVirtualPath, resourceKey) ?? &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty).ToString();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; mergeTokens(resource, args);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Localize(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; System.Web.UI.Page page, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resourceKey, &lt;span style="color: #0000ff"&gt;params&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resource = (HttpContext.GetLocalResourceObject(page.AppRelativeVirtualPath, resourceKey) ?? &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty).ToString();&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; mergeTokens(resource, args);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; mergeTokens(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resource, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (resource != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; args != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; args.Length &amp;gt; 0)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(resource, args);&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; resource;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;It is substantially shorter and defers to a base class. System.Web.MVC.ViewUserControl inherits from System.Web.UI.UserControl, so the call is true to it's application. I also extend System.Web.UI.Page.&lt;/p&gt;

&lt;p&gt;Lastly, there is the issue of a global resource. Since these resources are compiled and accessed at design time using dot notation (MyGlobalRes.MyKey) I felt that providing an extra function would not significantly shorten code or simplify developer's life. That is, given a resx file in the App_GlobalResources containing the file Zones.resx, containing a key Zone1 one would simply write out&lt;/p&gt;

&lt;div&gt;
  &lt;div class="csharpcode"&gt;
    &lt;pre class="alteven"&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &amp;lt;%= Resources.Zones.Zone1 %&amp;gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;or – if your resource is a template requiring tokens to be merged:&lt;/p&gt;

&lt;div&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;%= String.Format(Resources.Zones.Zone1,&lt;span style="color: #006080"&gt;"foo"&lt;/span&gt;,11) %&amp;gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Happy MVC Internationalization, localization and globalization!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132673"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132673" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/132673.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/06/07/localize-your-mvc-with-ease-again.aspx</guid>
            <pubDate>Mon, 08 Jun 2009 03:08:29 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/132673.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/06/07/localize-your-mvc-with-ease-again.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/132673.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/132673.aspx</trackback:ping>
        </item>
        <item>
            <title>Save The Date: time_t 1234567890</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/02/12/save-the-date-time_t-1234567890.aspx</link>
            <description>You know you are a geek when things like this seem of any importance.&lt;br /&gt;
It may comfort you to know that there are others who are excited about the buzz. It may disturb you. Make of it what you will:&lt;br /&gt;
&lt;br /&gt;
On Friday, &lt;span style="font-weight: bold;"&gt;February 13th 23:31:30 UTC 2009&lt;/span&gt; the time_t structure would contain the the number &lt;span style="font-weight: bold;"&gt;1234567890&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;The &lt;/span&gt;&lt;/span&gt;time_t is measures seconds past midnight of January 1 1970&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt; &lt;/span&gt;(see&lt;a href="javascript:void(0);/*1234462844526*/"&gt; Unix Epoc&lt;/a&gt;, POSIX time etc)&lt;br /&gt;
&lt;br /&gt;
You might celebrate UTC time - those of you not stuck in traffic in New York or at work in California. Or just do it according to your time zone: raise a toast,  save some doughnuts from doughnut-Friday or look at the sky or do triple click an icon or something.&lt;br /&gt;
&lt;br /&gt;
Here's a little java script to sneak onto your website which shows the time and the countdown:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;&amp;lt;script language="javascript" type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    function onTick()&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    {&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;        var t = Math.floor( ((new Date()).getTime()) /1000);&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;        var remaining = (1234567890 - t);&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;        var display = "Now: "  + t + ": " + remaining + " Sec. to 1234567890 (local time zone).";&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;        document.getElementById("_ShowTime").innerHTML = display;&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    }&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    &lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    setInterval('onTick()', 1000);&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;    &lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 0, 128);"&gt;&amp;lt;div id="_ShowTime" style="height: 1.1em; color: white; background-color: navy; font-weight:bolder; border: dashed 1px blue;"&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(0, 0, 128);" /&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129365"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129365" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/129365.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/02/12/save-the-date-time_t-1234567890.aspx</guid>
            <pubDate>Thu, 12 Feb 2009 16:25:47 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/129365.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/02/12/save-the-date-time_t-1234567890.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/129365.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/129365.aspx</trackback:ping>
        </item>
        <item>
            <title>The Flash Myth</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/02/01/the-flash-myth.aspx</link>
            <description>&lt;p&gt;Frustrated with square looking web pages, many web designers look to Flash. In addition to freedom of graphic expression, Flash brings interaction and transition effects which are difficult or impossible to duplicate. Why then shouldn't all websites be Flash laden? Several reasons pop to mind: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Loading speed&lt;/strong&gt;: Way too often, flash movies load complex graphics, forcing the viewer to stare at some progress bar. For people who want to quickly access information this is a huge turn off. A "skip intro" sometimes viewed as lame. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;SEO&lt;/strong&gt;: Flash based sites rarely are digestible or well ranked by search engines. You use flash – you lose top slots in natural search results. It's that simple &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Form over content&lt;/strong&gt;: Flash designs - as beautiful and engaging as they may be – all too often sacrifice text and information quantity in order to not disturb the layout or fit within the containing graphics. Again, ranking will suffer (low authority), viewers seeking comprehensive data will navigate away or become frustrated attempting to dig up more details by clicking every button and link in the movie. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt; Cost&lt;/strong&gt;: Although many good web designers can produce Flash movies, the good ones are fewer and more expensive. The problem compounds with natural workplace attrition. The ability to modify the original design, extend the site or give the site a "facelift" becomes constrained or expensive. All too often the original design does not lend itself well to rearrangement or extension. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;QA&lt;/strong&gt;: Automated testing of Flash UI sites is difficult or impossible because the results may not be capture-able by testing tools – and that's in the good case where the inputs are automatable. Unit testing for ActionScript is available by supporting frameworks these days, but finding implementations which include continuous integration is still rare. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Ease of use&lt;/strong&gt;: Often, the design focus reflects the author's perspective. As long as the viewer wants to view information the way the designer does, everything flows well. Once the viewer wants to navigate in a different way, all bets are off. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Stickiness&lt;/strong&gt;: By far, one of the more compelling reasons for having used a Flash based site was to engage the viewer and strengthen the brand. The delivery on the promise is a bit mixed. Although some interaction does increase the stickiness of the site, other designs may suffer from slow load and skimpy content actually detracting from the overall perceived quality. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If while reading the points mentioned above you think to yourself "It seems that many of the points indicate poor design – not a technology limitation" you are right, and I couldn't agree with you more.  &lt;/p&gt;
&lt;p&gt;Yet a good amount of sites out there suffer from these issues. Most of these sites would have been better served producing an HTML / DHTML / CSS + Ajax etc. In fact, my motivation for writing this came from a restaurant website I visited today. While scanning through listings and attempting to learn more, I was forced to watch tab after tab of progress bar latency in order to see the menu, the location, the about us etc. That site would have been cheaper to upgrade by anybody, rank higher on search engines, load faster and create less frustrated visitors. The KISS principle does apply. The pictures were beautiful; the layout was very appealing, the information organized – but the experience utterly annoying. Is that the best impression the business owner could impart on a potential customers? &lt;/p&gt;
&lt;p&gt;In another instance, I was searching for a specialty product, and found it about 40 miles away. After having spent the time driving there and making a purchase, I discovered a location much closer to my house. What made the different? The far store had a website with full online catalog in HTML. The close by store had a flash only site. Snazzy – but missed a sale.  &lt;/p&gt;
&lt;p&gt;I have been to some sites that make great use of Flash though, and it would be foolish to discount the technology for its potential pitfalls. On the contrary – its adoption and application should be studied and considered when new design projects com up. There are many sites containing laundry lists of good vs. bad design. This article is no such list. But when is Flash well suited?  &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Where a custom tool is created for order processing. Photo order sites, custom printing, fashion model virtualization etc. In these cases Flash serves an interactive function and is typically not the whole site. &lt;/li&gt;
    &lt;li&gt;Where little textual information is required. Walkthroughs, product 360 views, design concept sites targeting highly interested viewers who don't mind waiting for content and where alternative information sources are not available. &lt;/li&gt;
    &lt;li&gt;For isolated rich interaction: Games, presentations and doodads that keep the visitor happy watching and engaged – as a single section of the site. &lt;/li&gt;
    &lt;li&gt;Offline (DVD, CD) or downloadable media presentations, manuals etc. &lt;/li&gt;
    &lt;li&gt;Anywhere that you can do a better job at winning the mind of the visitor without losing another 3 along the way. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bottom line – use it wisely. If you suspect that any of the problems mentioned above might harm your online business, consider alternatives. And yes, by all means – do use a flash player to play video clips on the net. It is very well suited for that. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129132"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129132" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/129132.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/02/01/the-flash-myth.aspx</guid>
            <pubDate>Mon, 02 Feb 2009 03:41:16 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/129132.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/02/01/the-flash-myth.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/129132.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/129132.aspx</trackback:ping>
        </item>
        <item>
            <title>Pex gotcha – watch your predicate expressions</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/01/26/pex-gotcha--watch-your-predicate-expressions.aspx</link>
            <description>&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Just came back from another great &lt;a href="http://www.socalcodecamp.com/"&gt;SoCal Code Camp&lt;/a&gt;. I had some valuable insights and discussions about TDD and the use of Pex. Thank you attendees! &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;While developing the presentation for Pex, I ran into a situation where the Pex.Assume() did not seem to work at all: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Consider the function  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        &lt;span style="color: blue;"&gt;public&lt;/span&gt; 			&lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;short&lt;/span&gt;&amp;gt; MakeList(&lt;span style="color: blue;"&gt;short&lt;/span&gt; baseNum, &lt;span style="color: blue;"&gt;short&lt;/span&gt; count) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            &lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;short&lt;/span&gt;&amp;gt; result = &lt;span style="color: blue;"&gt;new&lt;/span&gt; 			&lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;short&lt;/span&gt;&amp;gt;(count); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;short&lt;/span&gt; i = 1; i &amp;lt;= count; i++) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;                result.Add((&lt;span style="color: blue;"&gt;short&lt;/span&gt;)(baseNum * i)); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            &lt;span style="color: blue;"&gt;return&lt;/span&gt; result; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Pex correctly identifies a potential flaw where the multiplication (baseNum * i) would result in overflow. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Adding a filter &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    &lt;span style="color: rgb(43, 145, 175);"&gt;PexAssume&lt;/span&gt;.IsTrue(baseNum * count &amp;lt; &lt;span style="color: blue;"&gt;short&lt;/span&gt;.MaxValue); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Seems like it would do the trick – but it doesn't. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Several rebuilds, clean solution, shake heads and searches for bugs later I found the issue: The predicate provided to PexAssume.IsTrue(predicate) produced an overflow! So when pex explores it would have tripped the condition I was trying to avoid by evaluating the parameters I tried to filter out. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;The fix was to rewrite the filter as: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;PexAssume&lt;/span&gt;.IsTrue(&lt;span style="color: blue;"&gt;short&lt;/span&gt;.MaxValue / count &amp;gt; baseNum); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;Here, the math would not produce an overflow. Combined with PexAssume(count&amp;gt;0) and PexAssume(baseNum&amp;gt;0) my now filters work as (I) expected. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: 10pt;"&gt;The take home is pretty obvious – ensure the predicate does not throw – but identifying it took a bit of head scratching. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=128973"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=128973" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/128973.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/01/26/pex-gotcha--watch-your-predicate-expressions.aspx</guid>
            <pubDate>Mon, 26 Jan 2009 16:35:47 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/128973.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/01/26/pex-gotcha--watch-your-predicate-expressions.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/128973.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/128973.aspx</trackback:ping>
        </item>
        <item>
            <title>Code Camp coming up</title>
            <link>http://geekswithblogs.net/nuri/archive/2009/01/16/code-camp-coming-up.aspx</link>
            <description>&lt;p&gt;It's that time of year again - Code Camp is next week, hosted at Cal State Fulerton.&lt;/p&gt;
&lt;p&gt;Many good presenters, many good sessions.&lt;/p&gt;
&lt;p&gt; Show up for one day both two, it's free to attend!&lt;/p&gt;
&lt;a href="http://www.socalcodecamp.com/"&gt;Check it out, come by&lt;/a&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=128740"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=128740" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/128740.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2009/01/16/code-camp-coming-up.aspx</guid>
            <pubDate>Sat, 17 Jan 2009 04:25:55 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/128740.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2009/01/16/code-camp-coming-up.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/128740.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/128740.aspx</trackback:ping>
        </item>
        <item>
            <title>Code better – measure your code with NDepend</title>
            <link>http://geekswithblogs.net/nuri/archive/2008/11/08/code-better--measure-your-code-ndepend.aspx</link>
            <description>&lt;p&gt;If you ask the average developer what might be done to improve code, they would probably come up with "use design patterns" or "do code reviews" or even "write unit tests". While all these are valid and useful, it is rare to hear "measure it". It's odd, when you think about it, because most of us consider ourselves scientists or sorts. Some of use obtained a degree in computer science, and we view the coding practice and a deterministic endeavor. Why is it then that we don't measure our work using standard methodologies and objective tools and evidence? &lt;/p&gt;
&lt;p&gt;For one, some of us are blissfully unaware of the existence of such methods. Indeed, the science of quality measurement of code has been the domain of university halls more so than practiced in the "real" world. Six Sigma and CMMI are probably the more familiar endeavors prescribing some sort of measure/improve into the coding practice but both include scant little in terms of measuring code itself. Rather they focus on the results of the software endeavor not on the "internal quality" of code. &lt;/p&gt;
&lt;p&gt;Another reason for low adoption of code quality measurement is lack of tools. We have wealth of guidance instruments, but less so code quality focused. For example, FxCop and the addition of Code Analysis to VSTS have brought huge contribution to code reviewing and uniformity in coding among teams. But let's face it – with so much guidance, it's all too easy to either dismiss the whole process as "too picky" or focus too much on one aspect of coding style rather than the underlying runtime binary. This is to say that it is very possible that what would be considered "good style" may not yield good runtime, and vice-versa. &lt;/p&gt;
&lt;p&gt;For a professional tool which enables you to view, understand, explore, analyze and improve your code look no further than NDepend. (&lt;a href="http://www.ndepend.com"&gt;www.ndepend.com&lt;/a&gt;). The tool is quite extensive and robust, and has matured in its presentation, exploration and integration capabilities becoming a great value for those of use interested digging deeper then the "my code seems to work" crowd. &lt;/p&gt;
&lt;p&gt;The installation is fairly straightforward. You pretty much unpack the download and place your license file in your installation directory. Upon running the tool, you can chose to install integration to VS2005, VS2008 and Reflector (now a RedGate property btw). &lt;/p&gt;
&lt;p&gt;Before using the tool for the first time, you can watch a few basic screen casts available from NDepend. The videos have no narration, so I found myself using the pause button if the text balloons flew by a bit quick. But that's no big deal with a 3-5 minute video. Once you get comfortable with the basics, you can almost immediately reap the benefits. Through a very relevant set of canned queries and screens you can quickly get a feel for how your code measures up. A graphic "size gram" presents methods, types, classes, namespaces or assemblies in varying sizes according to measures like lines of code (LOC – either the source itself or the resultant IL), Cyclometric Complexity and other very useful views of code cohesiveness and complexity. This visual let's you quickly identify or drill into the "biggest offender". &lt;/p&gt;
&lt;p&gt;Once you chose a target for exploration, the view in the assembly-method tree, the graphic size-gram and the dependency matrix all work in tandem: you chose an element in one, and the focal point shifts or drills down in the other two. There is also a pane which acts like a context menu which displays the metrics numbers for the selected method, field, assembly etc. This allows you to get the summary very quickly at any given point of your exploration. &lt;/p&gt;
&lt;p&gt;When you use the dependency matrix, method or types and their dependents are easily correlated. A measure of code quality is how tightly different types are coupled or dependent on each other. Theory is that if a dependency tree is too deep or too vast, change in a type will ripple through a lot of code whereas shallow or narrow dependency will have less dramatically affected by change. So it's a great thing to have a measure of your dependency relationships among your classes and assemblies. This measure tends to affect code most in the maintenance phase, but of course is as useful during initial prototype/refactor cycles pre-release. &lt;/p&gt;
&lt;p&gt;Another great feature is a dependency graph, producing a visual map of dependencies among the assemblies analyzed. I have found it very useful when "cold reading" legacy code I was charged in maintaining. Using the visualization I could more quickly determine what's going on and understand how pieces of code work together rather than follow painstakingly with bookmarks and "follow the code" with a debugger. &lt;/p&gt;
&lt;p&gt;As for the metrics themselves, you would probably choose your own policy regarding measures and their relevance. For one, the numbers are great as relative comparison of various code pieces. You may find that some dependencies are "very deep" – which in theory is "bad" – but that the indication points to a base class which you designed very well and serves as the base for everything. For an extreme example, most of us will agree that the "deep dependency" on System.String is well justified and doesn't merit change. It is important for the user to understand and digest the metrics in context, and draw appropriate conclusions. &lt;/p&gt;
&lt;p&gt;The tool is built on an underlying query technology called CQL. Once a project is analyzed, the database of findings is exposed both through built in queries. These queries can be modified and new queries can be built to correlate your important factors. Quite honestly, I have not gotten to a point of need for customization yet. The existing presentations are very rich and useful out of the box. One instance where you might want to produce custom queries  would be to exclude known "violations" by adding a where clause, thereby preventing code you already analyzed and mitigated from appearing or skewing the view of the rest of your code. &lt;/p&gt;
&lt;p&gt;In summary, I found NDepend very useful in examining legacy and new code. It gave me insights beyond empirical style oriented rules. It is much more informative to me to have a complexity measure or IL-LOC rather than a rule like "methods should not span more than 2 screen-full". Microsoft does include code metrics in VS 2010, and code analysis in VSTS or testing editions. If that is not within your budget, then you can have NDepend today and gain valuable insight right away. I would advise taking it slow in the beginning because there is a slight learning curve to the tool usage and navigation,  and ascribing relevant weight to the findings takes time. But once you get a hang of it, it becomes indispensible.  &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126894"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126894" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/126894.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2008/11/08/code-better--measure-your-code-ndepend.aspx</guid>
            <pubDate>Sat, 08 Nov 2008 21:32:20 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/126894.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2008/11/08/code-better--measure-your-code-ndepend.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/126894.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/126894.aspx</trackback:ping>
        </item>
        <item>
            <title>Code generatior for Visual Studio - Denum</title>
            <link>http://geekswithblogs.net/nuri/archive/2008/11/02/code-generatior-for-visual-studio---denum.aspx</link>
            <description>Annuouncing a newly added a &lt;a href="javascript:void(0);/*1225661011279*/"&gt;Codeplex &lt;/a&gt;project "Denum" code generator.&lt;br /&gt;
&lt;br /&gt;
The Denum is a class / pattern for representing fairly static metadata from a database in an in-memory structure.&lt;br /&gt;
The structure behaves much like an Enum, but contains static members for each data member so that compile time type checking helps in transparency and coherency of your application logic and the build itself against the database version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126506"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126506" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/126506.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2008/11/02/code-generatior-for-visual-studio---denum.aspx</guid>
            <pubDate>Sun, 02 Nov 2008 19:26:17 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/126506.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2008/11/02/code-generatior-for-visual-studio---denum.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/126506.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/126506.aspx</trackback:ping>
        </item>
        <item>
            <title>PDC 2008</title>
            <link>http://geekswithblogs.net/nuri/archive/2008/10/28/pdc-2008.aspx</link>
            <description>&lt;p&gt;Mind boggling things unvailed at &lt;a href="http://www.microsoftpdc.com"&gt;PDC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One big thing to decide is going to be our relation to the cloud.&lt;/p&gt;
&lt;p&gt;Cloud computing has hit big and the whole idea of SAS making big business invest big.&lt;/p&gt;
&lt;p&gt;Where do we draw the line? Hoe much of our software, data and service runs local vs. remote?&lt;/p&gt;
&lt;p&gt;How do we develop good measure for decisionmaking here?&lt;/p&gt;
&lt;p&gt;At the very least, aspect to be considered:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Latency&lt;/li&gt;
    &lt;li&gt;Scale&lt;/li&gt;
    &lt;li&gt;Time to market&lt;/li&gt;
    &lt;li&gt;Security&lt;/li&gt;
    &lt;li&gt;New opportunities not available if you are just "running local" such as ms Live services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the very least, if we created a startup on Azure - what is the path of migration off it if / when more local control is necessary? &lt;/p&gt;
&lt;p&gt;Asking these questions when architecting your new cloud based application is bound to have long lasting ramifications when your application usage reaches maturity.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126310"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126310" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/126310.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2008/10/28/pdc-2008.aspx</guid>
            <pubDate>Tue, 28 Oct 2008 18:20:34 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/126310.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2008/10/28/pdc-2008.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/126310.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/126310.aspx</trackback:ping>
        </item>
        <item>
            <title>WCF Serialization – new in .NET framework 3.5 sp1</title>
            <link>http://geekswithblogs.net/nuri/archive/2008/10/13/wcf-serialization--new-in-.net-framework-3.5-sp1.aspx</link>
            <description>&lt;p&gt;You may be surprised to find that classes are serialized by WCF without any [DataContract] attribute attached to them. I certainly was.
&lt;/p&gt;&lt;p&gt;When WCF came out, there was much fanfare of the new, improved, superior WCF serializer (justified IMHO). The main policy sizzle was that unlike the [Serializable] marking a POCO object and then [NonSerialized] attribute marking specific fields (opt-out), WCF will now use "opt-in": Only properties specifically decorated will be serialized.
&lt;/p&gt;&lt;p&gt;This serialization policy was clearly expressed, and the side effect of it all is that suddenly I have a bunch of projects that fail some unit tests. Upon &lt;a href="http://www.pluralsight.com/community/blogs/aaron/archive/2008/05/13/50934.aspx"&gt;digging&lt;/a&gt;, I found that SP1 has introduced a new kink: if you don't decorate your class at all (omit / not add the [DataContract] attribute) then the object becomes "fully" serializable by WCF. All public properties will be automatically included.
&lt;/p&gt;&lt;p&gt;This may seem as a huge step back to those that relied on the opt-in feature to hide certain classes from the serializer. This also may be a huge sigh of relief to those who cringed at the effort of (re)decorating all their message and value objects for WCF.
&lt;/p&gt;&lt;p&gt;Note that now with SP1, if you do decorate an object with [DataContract] then the old rules apply – only properties with [DataMember] will be serialized. So to be selective, you may still decorate with [DataContract] and then selectively decorate only the properties you want.
&lt;/p&gt;&lt;p&gt;I don't know what led to the exact decision, and the syntax nuance definitely walks a fine line. One could argue that classes without decoration now serialize without effort, but ones marked for WCF specifically still behave as previously advertised.
&lt;/p&gt;&lt;p&gt;All in all, 2 hours of head scratching in disbelief, 1 hour to change some unit test expectations, not too awful. Long live refactoring tools in Visual Studio!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=125818"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=125818" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/nuri/aggbug/125818.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Nuri Halperin</dc:creator>
            <guid>http://geekswithblogs.net/nuri/archive/2008/10/13/wcf-serialization--new-in-.net-framework-3.5-sp1.aspx</guid>
            <pubDate>Mon, 13 Oct 2008 15:08:45 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/nuri/comments/125818.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/nuri/archive/2008/10/13/wcf-serialization--new-in-.net-framework-3.5-sp1.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/nuri/comments/commentRss/125818.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/nuri/services/trackbacks/125818.aspx</trackback:ping>
        </item>
    </channel>
</rss>