<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  >

<channel>
  <title>CodeGear TeamB Blogs Master Site Feed</title>
  <link>http://blogs.teamb.com/feeds</link>
  <description>Shows all posts, comments, and pages from all blogs on this WPMU powered site</description>
  <pubDate>Fri, 05 Mar 2010 20:48:27 +0000</pubDate>
  <generator>http://wordpress.org/?v=2.6.2</generator>
  <language>en</language>
  <item>
    <title>Don&#8217;t Depend Upon the ASP.NET Membership Tables</title>
    <link>http://blogs.teamb.com/craigstuntz/2010/03/05/38558/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2010/03/05/38558/#comments</comments>
    <pubDate>Fri, 05 Mar 2010 20:48:27 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38558</guid>
    <description><![CDATA[One very popular option for implementing user security in ASP.NET is to use Forms Authentication with the SQL Server membership provider. This provider creates several database tables to store user-related information, as well as a number stored procedures.
From time to time, a developer will attempt to add the ASP.NET Membership/Forms Authentication tables to their Entity [...]]]></description>
      <content:encoded><![CDATA[<p>One very popular option for implementing user security in ASP.NET is to <a href="http://msdn.microsoft.com/en-us/library/ms998317.aspx">use Forms Authentication with the SQL Server membership provider</a>. This provider creates several database tables to store user-related information, as well as a number stored procedures.</p>
<p>From time to time, a developer will attempt to add the ASP.NET Membership/Forms Authentication tables to their Entity Framework model (or LINQ to SQL, NHibernate, etc.) model. Before doing this, they will often have created referential constraints against these tables. When the mapping doesn&#8217;t work out quite the way they planned, <a href="http://stackoverflow.com/search?q=[entity-framework]+aspnet_users">they will ask how to make the mapping work</a>.</p>
<p><strong>There&#8217;s only one correct answer to this question: Don&#8217;t do it at all!</strong></p>
<p>There are a number of good reasons why you should not make your database and code depend upon the SQL Membership Provider database schema. In this post, I will focus on a few of the most important:</p>
<ul>
<li>Separation of concerns</li>
<li>Membership and authentication providers are supposed to be interchangeable</li>
<li>The SQL Membership Provider database schema is an implementation detail</li>
</ul>
<h3>Separation of Concerns</h3>
<p>Your application&#8217;s data model is designed to fit your application domain. It will change based upon the needs of the end users. It should not have to change because Microsoft decides to update the SQL membership provider, as well. That would violate the <a href="http://www.oodesign.com/single-responsibility-principle.html">single responsibility principle</a>. It is often <a title="Commercial Suicide Integration at the Database Level" href="http://devlicio.us/blogs/casey/archive/2009/05/14/commercial-suicide-integration-at-the-database-level.aspx">dangerous to combine data which is not closely related into a single data model</a>. This danger is compounded when data from two separate domains, written by entirely different companies, and designed for orthogonal purposes is shoehorned into a single entity model.</p>
<h3>Membership providers are supposed to be interchangeable</h3>
<p>One of the most important design intentions of the ASP.NET authentication and membership provider model is to make it easy to interchange providers. If you decide to stop using the SQL membership provider in transition to Open ID, domain authentication, Facebook authentication, etc., this should be a matter of, at most, a couple of days work to migrate data from one provider to the other, rather than a complete rewrite of your application, starting with the database and moving out from there.</p>
<h3>The SQL Membership Provider database schema is an implementation detail</h3>
<p>The publicly-documented interfaces to membership and forms authentication are the <a href="http://msdn.microsoft.com/en-us/library/system.web.security.membership.aspx">Membership</a> and <a href="http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.aspx">FormsAuthentication</a> types, respectively, as well as the <a title="authentication Element" href="http://msdn.microsoft.com/en-us/library/532aee0e.aspx">relevant</a> <a title="membership Element" href="http://msdn.microsoft.com/en-us/library/1b9hw62f.aspx">sections</a> of the Web.config file. If you write your code around these types, you have a reasonable expectation that your code will continue to work when the .NET framework is next updated. On the other hand, if you query the database directly, there is no guarantee that the schema will not change when the next version of .NET ships. If Microsoft makes a security-related change to the SQL membership provider, then it is conceivable that the schema could even change with a service pack. The cost of relying on an implementation detail is that you never really know.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38558&amp;akst_action=share-this" onclick="akst_share('38558', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F03%2F05%2F38558%2F', 'Don%26%238217%3Bt+Depend+Upon+the+ASP.NET+Membership+Tables'); return false;" title="Post to del.icio.us, etc." id="akst_link_38558" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Don%26%238217%3Bt%20Depend%20Upon%20the%20ASP.NET%20Membership%20Tables&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F03%2F05%2F38558%2F" id="akst_email_38558" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jqGrid and XSS Security</title>
    <link>http://blogs.teamb.com/craigstuntz/2010/02/08/38548/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2010/02/08/38548/#comments</comments>
    <pubDate>Mon, 08 Feb 2010 20:50:22 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38548</guid>
    <description><![CDATA[Version 3.5.2 of jqGrid included an important new feature:
Now when autoencode is set to true we encode the data coming from server and not only when we post it (secutity fix)
Prior to this, you were required to encode the data yourself.
Now personally, I think that should be the default. But it would have been a [...]]]></description>
      <content:encoded><![CDATA[<p>Version 3.5.2 of <a href="http://www.trirand.com/blog/">jqGrid</a> included <a href="http://www.trirand.com/jqgridwiki/doku.php?id=wiki:change#jqgrid_3.5.2_changes_and_fixes">an important new feature</a>:</p>
<blockquote><p>Now when <code>autoencode</code> is set to true we encode the data coming from server and not only when we post it (secutity fix)</p></blockquote>
<p>Prior to this, you were required to encode the data yourself.</p>
<p>Now personally, I think that should be the default. But it would have been a breaking change for the grid, since there are a few cases where you want to display unencoded data (I&#8217;ll discuss these exceptional cases in a second).</p>
<p>It&#8217;s really easy to make this the default for your application. Set the grid&#8217;s defaults before you create any grids:</p>
<blockquote>
<pre><code>    $.jgrid.defaults = $.extend($.jgrid.defaults, {
            autoencode: true,
            datatype: 'json',
            // etc....</code></pre>
</blockquote>
<p>You can override this in the rare cases when you don&#8217;t want encoded data by setting <code>autoencode</code> false when setting up your grid:</p>
<blockquote>
<pre><code>    $("#grid").jqGrid({
                    autoencode: false,
                    url: "/Some/Path",
                    // etc....,</code></pre>
</blockquote>
<p>So why wouldn&#8217;t you want to use this setting? I can think of two reasons:</p>
<ol>
<li>The server is returning markup which you don&#8217;t want to encode. If you have a server method which is returning markup (e.g., "<code>&lt;img src=</code>&#8230;"), then you won&#8217;t want the grid to encode it. It then becomes your responsibility to sanitize the rest of the grid data on the server.</li>
<li>There is a performance cost to doing the encoding in JavaScript. If you are <em>absolutely certain</em> that the server method you&#8217;re calling can return only sanitized data, then you can turn off the auto encoding and save this cost. Note that many JSON encoders, such as the "<code>Json()</code>" method in ASP.NET MVC will <em>not</em> encode HTML by default.</li>
</ol>
<p>Note that you can only set <code>autoencode</code> at the grid level, not at the column level.</p>
<p>If you use <a href="http://www.trirand.com/jqgridwiki/doku.php?id=wiki:custom_formatter">custom formatters</a> in your grid, then you should note that the strings they return will not be HTML encoded, even if you set <code>autoencode</code> true. This is probably a good thing, since it is common to use custom formatters to return HTML. However, it means that if you write a custom formatter, then you must ensure that any user data contained in the string and returns is encoded. You can use the grid&#8217;s encoder, which is little more than a string replace on angle brackets, in a custom formatter as follows:</p>
<blockquote>
<pre><code>    myFormatter: <strong>function</strong>(cellval, opts, action) {
        <strong>if </strong>(cellval) {
            return $.jgrid.htmlEncode(cellval.Name + "");
        };
        <strong>return </strong>"";
    }</code></pre>
</blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38548&amp;akst_action=share-this" onclick="akst_share('38548', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F02%2F08%2F38548%2F', 'jqGrid+and+XSS+Security'); return false;" title="Post to del.icio.us, etc." id="akst_link_38548" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jqGrid%20and%20XSS%20Security&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F02%2F08%2F38548%2F" id="akst_email_38548" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Entity Framework Models and Source Control</title>
    <link>http://blogs.teamb.com/craigstuntz/2010/02/03/38542/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2010/02/03/38542/#comments</comments>
    <pubDate>Wed, 03 Feb 2010 19:58:19 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Databases]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38542</guid>
    <description><![CDATA[As you&#8217;re probably aware, an Entity Framework model is stored in a single XML file, with the extension EDMX. Developers occasionally ask if this means that two people cannot work on the entity model concurrently. My answer to this is, "It depends." But I can give you some tips to make it easier.
Obviously, if you [...]]]></description>
      <content:encoded><![CDATA[<p>As you&#8217;re probably aware, an Entity Framework model is stored in a single XML file, with the extension EDMX. Developers occasionally ask if this means that two people cannot work on the entity model concurrently. My answer to this is, "It depends." But I can give you some tips to make it easier.</p>
<p>Obviously, if you use a source control tool which locks files on check out, then working concurrently on just about anything will be impossible. So I&#8217;m going to presume that your source control tool supports working concurrently, without locks, and has a decent merge tool to handle conflicts at check-in.</p>
<p>We tend to think of the EDMX files as having three sections:</p>
<ul>
<li><strong>CSDL</strong>, which describes the client schema. This will be used when generating code for your entity classes.</li>
<li><strong>SSDL</strong>, which describes the storage schema, more commonly known as your database metadata.</li>
<li><strong>MSL</strong>, which describes the relationship between the first two.</li>
</ul>
<p>In reality, however, the EDMX file has two main sections. The first, <code>edmx:Runtime</code>, contains the three <em>sub</em>-sections described above. The second, <code>edmx:Designer</code>, contains a couple of important properties, such as <code>MetadataArtifactProcessing</code>, plus <em>a lot</em> of information about the position of objects on the GUI designer, in a sub-node called <code>edmx:Diagrams</code>. The illustration below should make this clear:</p>
<p><a href="/files/2010/02/edmx_2309.png"><img src="/files/2010/02/edmx_2309.png" alt="" width="677" height="203" /></a></p>
<p>Why is this important? My experience is that any decent merge tool doesn&#8217;t tend to have any problem merging what we typically think of as the "EDMX", namely the CSDL, SSDL, and MSL. It is well-formed XML with descriptive tags; it&#8217;s the sort of thing that text merge tools tend to do very well with. There are a couple of tips worth knowing, but before I describe them, I&#8217;d like to focus on the more common issue with EDMX merges.</p>
<p>In my experience, if two people change the layout of entities in the designer and then attempt to merge, the merge will probably fail. Moreover, you will find it difficult to impossible to fix this up manually, something which is generally fairly easy with merges of source code or other parts of the EDMX. When you look at what is in the <code>edmx:Diagrams</code> node, you will quickly understand why:</p>
<p><a href="/files/2010/02/diagrams_2312.png"><img src="/files/2010/02/diagrams_2312.png" alt="" width="500" height="328" /></a></p>
<p>I strongly suspect that this "feature" is not specific to the Entity Framework designer, but rather is shared amongst all of Visual Studio&#8217;s various diagramming tools. At any rate, I think you will have a difficult time merging XML like this, so I have two recommendations regarding merging and EDMX files:</p>
<ul>
<li>If you are going to have two or more developers work on an EDMX file concurrently, then don&#8217;t change anything in the designer. If two or more people do this, it almost guarantees a conflict on check-in.</li>
<li>The other side of the coin is that if you must change something in the designer, then you should give a heads-up to other developers, and exclusively lock the EDMX file while you work.</li>
</ul>
<p>That said, we don&#8217;t generally use the GUI designer at all. It is too unwieldy to have more than a dozen or so types on a single design surface. On the other hand, the tree-style Model Browser is quite useful. I suggest using the Model Browser instead of the GUI designer to navigate your entity model.</p>
<p>Perhaps a future version of the Entity Framework designer will allow for multiple diagrams within a single entity model, somewhat like SQL Server diagrams. If each diagram had its own node in the XML, you might even be able to merge them.</p>
<p>If you steer clear of issues with the designer, then you will typically find that EDMX changes can be automatically merged by any decent merge tool (unless, of course, they actually conflict). In the unlikely event, however, that your merge tool reports a conflict, and you don&#8217;t think it&#8217;s an actual conflict between your changes and those made by the other developer, it does help to understand how the "Update Model from Database" wizard updates existing EDMX:</p>
<ol>
<li>The wizard will generate new SSDL from scratch. It will then go through the newly generated SSDL, and replace each matching node in the existing SSDL with the newly generated version. There are a few SSDL features which are not supported by the designer/wizard, such as will, and these will be left alone, if they exist in your model.</li>
<li>Any new entities or new properties of existing entities will have corresponding nodes added to the CSDL and MSL. But existing entities and properties will not have their CSDL and MSL updated, because the wizard presumes that you want to keep any changes you may have made to them.</li>
</ol>
<p>Therefore, when multiple developers are updating an EDMX file concurrently, they should use the same database. This will tend to make SSDL changes merge without conflict, and allows you to simply overwrite any false conflicts (merge tool failures) in the SSDL, because you can be confident that it was generated from the same object in the same database. But if you&#8217;ve manually customized your SSDL (i.e., edited the SSDL section of the EDMX as text), then you should keep an eye on your changes, to make sure that the wizard does not overwrite them. Most people never do this, though.</p>
<p>On the other hand, changes to the CSDL and MSL must be reviewed carefully in the unlikely event that there are conflicts in the merge, because you, or the other developer, may have made customizations to the mapping or entity types which you want to keep.</p>
<p>Finally, it is worth mentioning that <a href="http://blogs.msdn.com/adonet/pages/feature-ctp-walkthrough-code-only-for-the-entity-framework.aspx">the Entity Framework version 4 supports "code only" models</a> which do not use EDMX files at all. If you prefer designing your entity model via source code, you can choose this option.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38542&amp;akst_action=share-this" onclick="akst_share('38542', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F02%2F03%2F38542%2F', 'Entity+Framework+Models+and+Source+Control'); return false;" title="Post to del.icio.us, etc." id="akst_link_38542" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Entity%20Framework%20Models%20and%20Source%20Control&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F02%2F03%2F38542%2F" id="akst_email_38542" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>join in LINQ to SQL and LINQ to Entities Considered Messy, Redundant</title>
    <link>http://blogs.teamb.com/craigstuntz/2010/01/13/38525/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2010/01/13/38525/#comments</comments>
    <pubDate>Wed, 13 Jan 2010 20:24:20 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38525</guid>
    <description><![CDATA[In this post I will demonstrate that use of the join keyword in LINQ to SQL and LINQ to Entities is nearly always wrong. LINQ queries which you write with the join keyword are harder to read and write than queries you write using associations, and they require knowledge of database metadata which is not [...]]]></description>
      <content:encoded><![CDATA[<p>In this post I will demonstrate that use of the <code>join</code> keyword in LINQ to SQL and LINQ to Entities is nearly always wrong. LINQ queries which you write with the <code>join</code> keyword are harder to read and write than queries you write using associations, and they require knowledge of database metadata which is not required otherwise. This introduces the potential for errors and makes maintenance harder.</p>
<p><a href="http://www.google.com/search?q=left+join+linq">Many people ask how to do a "left join" in LINQ to SQL</a>, and unfortunately, the answer they <a href="http://solidcoding.blogspot.com/2007/12/left-outer-join-in-linq.html">nearly</a> <a href="http://geekswithblogs.net/AzamSharp/archive/2008/04/07/121103.aspx">always</a> <a href="http://stackoverflow.com/questions/1092562/left-join-in-linq">get</a> — "Use <code>DefaultIfEmpty</code>!" — is, in my opinion, terrible advice. Let&#8217;s implement the same query with and without the <code>join</code> keyword, and then compare the readability of the queries, the functionality, the knowledge required to write the query, and the maintainability of the code. I think you will find that using associations wins on every single criterion I examine.</p>
<p>I&#8217;m going to use the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en">Northwind demo database</a> for this example, since many people are familiar with its structure. I created a LINQ to SQL model for Northwind by simply dragging all of the tables in the database onto the LINQ to SQL designer. The only change I made to the model generated by the designer is to rename the "Employee1" property on the generated "Employee" type to the more descriptive name "Supervisor." I&#8217;m using LINQ to SQL for this demo, but everything I&#8217;m saying here applies equally to LINQ to Entities.</p>
<h3>"Left" Joins</h3>
<p>Let&#8217;s imagine that I am asked to produce a web page listing all employees in a company, along with their supervisor, if any. This requires a "left join," in SQL terms, because not all employees have a supervisor. I&#8217;ll project onto a presentation model, <a href="http://blogs.teamb.com/craigstuntz/2009/12/31/38500/">just like I do in LINQ to Entities</a>. Using the association properties generated by LINQ to SQL, this is quite simple:</p>
<p><a href="/files/2010/01/association-left_2275.png"><img src="/files/2010/01/association-left_2275.png" alt="" /></a></p>
<p>This is fairly readable. The one thing that you need to know is that both LINQ to SQL and LINQ to Entities coalesce nulls. This means that on a row where <code>e.Supervisor</code> is null, you will not get a <code>NullReferenceException</code> in the assignment to <code>SupervisorName</code> and <code>SupervisorBirthDate</code>, as you would with LINQ to Objects. Instead, null will be assigned. Therefore, it is important that <code>EmployeeListItem.SupervisorBirthDate</code> is of type <code>DateTime?</code> (a.k.a. <code>Nullable&lt;DateTime&gt;</code>) instead of the non-nullable <code>DateTime</code>.</p>
<p>Let&#8217;s compare that to the equivalent query using the <code>join</code> syntax, using the mysteriously popular<code> DefaultIfEmpty</code> trick:</p>
<p><a href="/files/2010/01/join-left_2278.png"><img src="/files/2010/01/join-left_2278.png" alt="" width="442" height="189" /></a></p>
<p>Yuck! This is far less readable than the query above. Yet these two queries produce <em>exactly the same results</em>. If you don&#8217;t believe me, download the <a href="/files/2010/01/l2sapp_2290.zip">sample project attached to this post</a> and try it yourself. Perhaps even worse than the general unreadability of the "join version" is the fact that this query requires knowledge of the structure of the database which is already present in the DBML (or EDMX, in the case of the Entity Framework) model. This is a problem for two reasons. First, it&#8217;s an opportunity for programmers to make a mistake, which the first query eliminates. Second, it&#8217;s a potential maintenance issue if the foreign key definition ever changes in the database.</p>
<h3>"Inner" Joins</h3>
<p>Now let&#8217;s compare an example of an "inner join" using both my recommended method of associations and the LINQ <code>join</code> keyword. Here&#8217;s the association version. It&#8217;s so readable that there is very little to say about it:</p>
<p><a href="/files/2010/01/association-inner_2281.png"><img src="/files/2010/01/association-inner_2281.png" alt="" width="472" height="152" /></a></p>
<p>Here&#8217;s the <code>join</code> version:</p>
<p><a href="/files/2010/01/join-inner_2287.png"><img src="/files/2010/01/join-inner_2287.png" alt="" width="497" height="184" /></a></p>
<p>Again, these two queries do exactly the same thing, as you can confirm for yourself by running the demo project. The <code>join</code> version here shares all of the faults of the "left join" version above.</p>
<h3>API Consistency</h3>
<p>Thus far, I&#8217;ve been discussing LINQ to SQL. But what if I have an <code>Employee</code> instance and that like to examine the employee&#8217;s supervisor? I might write code like this:</p>
<p><a href="/files/2010/01/supervisor_2291.png"><img src="/files/2010/01/supervisor_2291.png" alt="" width="298" height="15" /></a></p>
<p>Now compare that code with the "association" and "join" query forms. You will see that using the associations makes the LINQ to SQL queries much more closely resemble how you work with the materialized entity objects in "regular" code. Again, I think this makes your code easier to read.</p>
<h3>What About Performance?</h3>
<p>Not surprisingly, the SQL generated by the equivalent association and join versions is close to identical. I would not expect to ever see a performance difference between the two syntaxes in terms of query execution time.</p>
<h3>Is It Ever Correct to Use join?</h3>
<p>The advantages of using associations are so strong that you may wonder why <code>join</code> exists in LINQ at all. Associations, however, are only helpful when they actually exist. There may be times when you need to "join" based on values which are not actually foreign keys. Or you may need to join between LINQ to SQL and LINQ to Objects.</p>
<h3>Running the Demo Project</h3>
<p>Here&#8217;s a <a href="/files/2010/01/l2sapp_2290.zip">the demo project.</a> To build and run it, you&#8217;ll need to Visual Studio 2010 Beta, SQL Server (Express is fine), and the Northwind demo database I linked above. Open the project, find the Web.config file in Solution Explorer and open it. Change the connectionString to point to your SQL Server. Now you should be able to run the application.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38525&amp;akst_action=share-this" onclick="akst_share('38525', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F01%2F13%2F38525%2F', 'join+in+LINQ+to+SQL+and+LINQ+to+Entities+Considered+Messy%2C+Redundant'); return false;" title="Post to del.icio.us, etc." id="akst_link_38525" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=join%20in%20LINQ%20to%20SQL%20and%20LINQ%20to%20Entities%20Considered%20Messy%2C%20Redundant&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F01%2F13%2F38525%2F" id="akst_email_38525" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Crossword No. 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2010/01/11/38518/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2010/01/11/38518/#comments</comments>
    <pubDate>Mon, 11 Jan 2010 19:07:06 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Crosswords]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38518</guid>
    <description><![CDATA[DotNetSlackers just published a crossword puzzle I created; you&#8217;ll see the grid below. The puzzle is focused on .NET and programming themes, including a Delphi reference here and there. The site editors wanted an article to go with the puzzle, so I wrote an article explaining how I created the puzzle. The article is full [...]]]></description>
      <content:encoded><![CDATA[<p>DotNetSlackers just published <a href="http://dotnetslackers.com/articles/net/Creating-a-programming-crossword-puzzle.aspx">a crossword puzzle I created</a>; you&#8217;ll see the grid below. The puzzle is focused on .NET and programming themes, including a Delphi reference here and there. The site editors wanted an article to go with the puzzle, so I wrote an article explaining how I created the puzzle. The article is full of spoilers, so if you&#8217;d like to try and solve the puzzle yourself scroll down to the bottom of the article to find the grid and clues before reading the article at the top.</p>
<p><a href="http://dotnetslackers.com/articles/net/Creating-a-programming-crossword-puzzle.aspx"><img src="/files/2010/01/crossword_2272.jpg" alt="" width="500" height="490" /></a></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38518&amp;akst_action=share-this" onclick="akst_share('38518', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F01%2F11%2F38518%2F', 'Crossword+No.+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_38518" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Crossword%20No.%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2010%2F01%2F11%2F38518%2F" id="akst_email_38518" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Projecting Onto a Presentation Model with the Entity Framework and ASP.NET MVC</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/12/31/38500/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/12/31/38500/#comments</comments>
    <pubDate>Thu, 31 Dec 2009 20:23:59 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38500</guid>
    <description><![CDATA[In this post, I will demonstrate how to map entity models to views in an ASP.NET MVC application without worrying about implementation details like eager loading, lazy loading, or having to manually optimize SQL for the task at hand. I will argue that expressing the relationship between an entity model in the presentation model in [...]]]></description>
      <content:encoded><![CDATA[<p>In this post, I will demonstrate how to map entity models to views in an ASP.NET MVC application without worrying about implementation details like eager loading, lazy loading, or having to manually optimize SQL for the task at hand. I will argue that expressing the relationship between an entity model in the presentation model in a LINQ projection is far simpler than other methods of doing this mapping.</p>
<p>Imagine that you&#8217;ve been asked to write a new web application to track employees for a customer, <a href="http://www.imdb.com/title/tt0151804/quotes">Chotchkies restaurant</a>. The application must use ASP.NET MVC and the ADO.NET Entity Framework. The user interaction designers have mocked up the following interface for editing an employee:</p>
<p><a href="/files/2009/12/employeeeditor_2243.png"><img src="/files/2009/12/employeeeditor_2243.png" alt="Employee editor" width="217" height="283" /></a></p>
<p>Upon seeing this mockup, your first recommendation is to fire the user interface designers. But management declines to follow your recommendation. So how should you implement this? Since this is a new application, you have no database, no entity model, nothing. Where to begin?</p>
<h2>Presentation Models</h2>
<p>For a variety of reasons, I always use strongly-typed views in my ASP.NET MVC applications. Also, I use presentation models instead of using entity types directly as the model type for my views.This allows the user interface and data models to evolve independently.</p>
<p>Because I am likely to want to build user interfaces using ASP.NET MVC 2&#8217;s Dynamic Templated Views, I need to decorate the view model with presentation concerns, like noting that the "Flair count" field is read-only in this particular view.</p>
<p>Especially in view of the less-than-compelling user interface markup, it&#8217;s important to realize that the design of the user interface is likely to change wildly over the course of implementing the application. When actual users begin to test the application, they will request changes to the user interface, and you need to be able to adapt to this.</p>
<p>This has two important implications: You must get a prototype to testers and end-users as fast as possible, and your user interface must not be deeply coupled to the rest of the application, given the high likelihood of change.</p>
<p>So based upon the user interface prototype above, the following presentation model might be reasonable:</p>
<p><a href="/files/2009/12/employeepresentation_2245.png"><img src="/files/2009/12/employeepresentation_2245.png" alt="" /></a></p>
<p>It&#8217;s now trivial to write an action which can be used to develop a view for editing the employee, and which matches the UI prototype above. Such an action might look like:</p>
<p><a href="/files/2009/12/employeeaction_2248.png"><img src="/files/2009/12/employeeaction_2248.png" alt="Demo employee action code" /></a></p>
<p>I&#8217;ll spare you the HTML. At this point, I have a running application which the user interaction designer can approve, and testers can try out. My total effort, thus far, is a few minutes of work. If I had started by designing a database and the data model, I would still have nothing to show for my efforts.</p>
<h2>Entity Model</h2>
<p>At some point however, you need to create a database and an entity model. That was, after all, part of the requirements you were given for the application. Knowing that there might be a need to reference people who are not employees, the entity model is going to have to look very different than the presentation model above. After some discussions with the business analyst, you learn that Chotchkies management is very serious about tracking employee flair, so a first attempt at an entity model might look like this:</p>
<p><a href="/files/2009/12/employeeentities_2254.png"><img src="/files/2009/12/employeeentities_2254.png" alt="" width="500" height="172" /></a></p>
<p>Now you can generate a database. At this point, you have a presentation model and an entity model, and need only wire them together.</p>
<h2>Projection</h2>
<p>Taking a collection of instances of one type, and mapping their properties onto a collection of instances of another type is often called mapping or projection. With older ORMs, which have either no or very limited LINQ support, this can be quite tedious, requiring manual code, the use of tools like AutoMapper, and a good deal of thinking about eager loading, lazy loading, and optimizing situations like the fact that we don&#8217;t actually want to load all of the flair for an employee here; we just need the count.</p>
<p>The Entity Framework, on the other hand, makes this very easy, as we can just express the relationship between the entity model and the presentation model with a LINQ expression:</p>
<p><a href="/files/2009/12/employeeaction_2257.png"><img src="/files/2009/12/employeeaction_2257.png" alt="" width="406" height="236" /></a></p>
<p>I&#8217;m glossing over some details here. In a real-world application, for example, we would use the repository pattern rather than grabbing the context directly in the controller. But the point of this post is shown in the code above:</p>
<p><em>By expressing the relationship between the entity model and the presentation model as a LINQ query, it is no longer necessary to worry about implementation details like eager loading versus lazy loading, optimizing the SQL for the Count and avoiding loading big properties not actually used here. </em>All of this can be — and is — derived from the query above, automatically.<em><br />
</em></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38500&amp;akst_action=share-this" onclick="akst_share('38500', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F12%2F31%2F38500%2F', 'Projecting+Onto+a+Presentation+Model+with+the+Entity+Framework+and+ASP.NET+MVC'); return false;" title="Post to del.icio.us, etc." id="akst_link_38500" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Projecting%20Onto%20a%20Presentation%20Model%20with%20the%20Entity%20Framework%20and%20ASP.NET%20MVC&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F12%2F31%2F38500%2F" id="akst_email_38500" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Delphi Developers: Go Buy CodeHealer</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/12/22/38495/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/12/22/38495/#comments</comments>
    <pubDate>Tue, 22 Dec 2009 11:56:00 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38495</guid>
    <description><![CDATA[If you&#8217;re doing commercial Delphi development and you&#8217;re not already doing static analysis in your automated build, go buy CodeHealer now. Nick Hodges has arranged a 1/2 price special offer.
There is no good reason not to use static analysis. If you are the sort of person who doesn&#8217;t allow hints and warnings in your code, [...]]]></description>
      <content:encoded><![CDATA[<p>If you&#8217;re doing commercial Delphi development and you&#8217;re not already doing static analysis in your automated build, go buy CodeHealer now. <a href="http://blogs.embarcadero.com/nickhodges/2009/12/21/39340">Nick Hodges has arranged a 1/2 price special offer</a>.</p>
<p>There is <em>no</em> good reason not to use static analysis. If you are the sort of person who doesn&#8217;t allow hints and warnings in your code, and has configured your build to fail on any hint or warning (and I hope that you are), then you&#8217;ll love static analysis; it takes this kind of discipline to the next level. Sure, it&#8217;s useful to find existing errors in your code, but the most important benefit is that it prevents new errors from being introduced.</p>
<p>The only remotely valid argument I&#8217;ve heard against using static analysis is that when you first use a static analysis tool against a legacy code base, you will typically see hundreds of rules violations, many of them incorrect. Cleaning all this up will be a lot of work, which you usually can&#8217;t take on all at once.</p>
<p>Unlike compiler hints and warnings, static analysis rule violations often happen when there is no underlying bug. When you develop new code, you can analyze any newly introduced rule violation and exclude it if necessary. But that&#8217;s not practical to do with legacy code. My approach to this problem is very simple: Turn off rules in your static analysis tool until all the rule violations go away.</p>
<p>What&#8217;s the point of buying a static analysis tool and then turning off half the rules? Well, the other half are still turned on, and they are now a part of your automated build, making it impossible to introduce new code which violates them. Moreover, you can go back and turn on the other rules a reasonable pace, say, one or two a week, fixing real issues that you find or excluding the particular violation if it turns out to be a non-issue, until they are all turned back on.</p>
<p>Once you have even a few static analysis rules turned on in your automated build, you&#8217;re getting some degree of quality control for very little expense. Integration testing costs money, every time you do it. Unit testing costs money every time you write new tests. Static analysis just works and keeps working, and costs you nothing more than a software upgrade once every couple years or so.</p>
<p>So static analysis in general is a good thing. What about CodeHealer in particular? Well, we have been using it for around three years now. It has been stable, and I&#8217;ve seen new versions released regularly. Also, I have never seen anything better for Delphi.</p>
<h4>Digression: Attributes</h4>
<p>When Delphi 2010 was released with the enhanced RTTI and custom attributes feature, many Delphi developers wondered what this feature would be useful for. In general, your source code describes the behavior of your application, and attributes describe your mechanisms (thanks to Eric Lippert for this concise description). Static analysis is an excellent example. Imagine that I want to exclude a static analysis rule in a particular case. This has nothing to do with the desired functionality of the application; rather, it&#8217;s more like a parameter to the automated build process.</p>
<p>That may sound a bit abstract, so let&#8217;s look at a specific example. FxCop, a static analysis tool for .NET code, has rule that should not introduce private types which are never used. But FxCop cannot detect the instantiation of types inside of a LINQ query. So in this case the rule is making a mistake; it is failing to detect that a type is, in fact, instantiated in my code. One possible solution to this issue would be to try and write a better rule. But that&#8217;s a lot of work, and there are only about two cases of this false positive in our entire source tree. So it&#8217;s easier to just suppress this message in the case of a false positive, which you can do with an attribute:</p>
<blockquote>
<pre><code>[System.Diagnostics.CodeAnalysis.SuppressMessage(
    "Microsoft.Performance",
    "CA1812:AvoidUninstantiatedInternalClasses",
    Justification = "It is instantiated in a query, which FxCop can't see.")]
<strong>private class </strong>ConsumerRow //...</code></pre>
</blockquote>
<p>This is far easier (and, I think, a better design) than what CodeHealer currently offers. I hope that future versions of CodeHealer will use this method, now that Delphi has attribute support.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38495&amp;akst_action=share-this" onclick="akst_share('38495', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F12%2F22%2F38495%2F', 'Delphi+Developers%3A+Go+Buy+CodeHealer'); return false;" title="Post to del.icio.us, etc." id="akst_link_38495" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Developers%3A%20Go%20Buy%20CodeHealer&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F12%2F22%2F38495%2F" id="akst_email_38495" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Interview With Me At Delphi.org</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/10/21/38492/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/10/21/38492/#comments</comments>
    <pubDate>Wed, 21 Oct 2009 12:35:39 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38492</guid>
    <description><![CDATA[Jim McKeeth interviewed me for Episode 34 of The Podcast At Delphi.org.
]]></description>
      <content:encoded><![CDATA[<p>Jim McKeeth interviewed me for <a title="34 – Craig Stuntz" href="http://www.delphi.org/2009/10/34-craig-stuntz/">Episode 34 of The Podcast At Delphi.org</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38492&amp;akst_action=share-this" onclick="akst_share('38492', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F21%2F38492%2F', 'Interview+With+Me+At+Delphi.org'); return false;" title="Post to del.icio.us, etc." id="akst_link_38492" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Interview%20With%20Me%20At%20Delphi.org&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F21%2F38492%2F" id="akst_email_38492" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Updating to ASP.NET MVC 2 Preview 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/10/05/38476/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/10/05/38476/#comments</comments>
    <pubDate>Mon, 05 Oct 2009 19:35:16 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38476</guid>
    <description><![CDATA[Last week, I updated our main development branch to ASP.NET MVC 2 preview 2 (from preview 1). In this post, I&#8217;ll list some of the features I&#8217;ve found, and also issues I encountered and how I resolved them.
New Features
Some of the new features of preview 2 have been discussed elsewhere, so I won&#8217;t rehash them. [...]]]></description>
      <content:encoded><![CDATA[<p>Last week, I updated our main development branch to ASP.NET MVC 2 preview 2 (from preview 1). In this post, I&#8217;ll list some of the features I&#8217;ve found, and also issues I encountered and how I resolved them.</p>
<h3>New Features</h3>
<p>Some of the new features of preview 2 have been discussed elsewhere, so I won&#8217;t rehash them. But I&#8217;ve also noticed that there is a new attribute, <code>[RequireHttps]</code>, which does what you would expect, when added to an action, and a new HTML helper, <code>Html.HttpMethodOverride</code>, which makes it easy to take a POST request and code as if the request were actually PUT or DELETE, by adding a hidden input containing a special value on the HTML form. This allows you to write your server in a more RESTful style, which will be suitable for user agents which know about the PUT and DELETE verbs, while maintaining compatibility with those (like browsers) which do not.</p>
<h3>MvcHtmlString</h3>
<p>After installing the new assembly into the GAC, I attempted to compile our existing projects. I got a compilation error on some of our custom HTML helpers, as the MVC extension methods like <code>Html.RouteLink</code> have been changed to return an instance of type <code>MvcHtmlString</code> instead of <code>String</code>. In many cases, I could just change the return type. However, the clear intention of the framework designers is that any HTML helpers which return HTML (with angle brackets) instead of "plain" text should return a <code>MvcHtmlString</code> instead of a <code>String</code>. So, in addition to changing the return types of methods where necessary to get those methods to compile, I also wanted to change the return types of any custom HTML helper which returned HTML containing angle brackets. It makes no difference today, but <a href="http://haacked.com/archive/2009/09/25/html-encoding-code-nuggets.aspx">in ASP.NET 4, there will be a new syntax to guard against XSS attacks</a>, and it makes sense to get ready for this by returning the correct type.</p>
<p>The trick here is that <code>MvcHtmlString</code> does not have a public constructor, so it&#8217;s not immediately obvious how to create one of these things. Perusing the MVC source code, I noticed that it does have a static <code>Create</code> method, and comments elsewhere in the source code indicate that this method should be used instead of the detected constructor. So you can now write a helper like this:</p>
<blockquote>
<pre><code><strong>public static</strong> MvcHtmlString Fud(<strong>this </strong>HtmlHelper helper)
{
    <strong>return </strong>MvcHtmlString.Create("&lt;acronym title=\"Fear, Uncertainty, and Doubt\"&gt;FUD&lt;/acronym&gt;");
}
</code></pre>
</blockquote>
<h3>JsonRequestBehavior</h3>
<p>ASP.NET MVC will now, by default, throw an exception when an action attempts to return JSON in response to a GET request. Unless you read the release notes carefully, you won&#8217;t discover this until runtime. This is in order to proactively defend against <a href="http://haacked.com/archive/2009/06/25/json-hijacking.aspx">a particular cross-site attack</a>. It is good to be safe by default, but you are only vulnerable to this attack under the following combination of circumstances:</p>
<ul>
<li>The data you&#8217;re returning is worth stealing.</li>
<li>The root data object in the JSON response is an array.</li>
<li>The requesting browser is not IE 8, or some other browser which doesn&#8217;t allow <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Object/DefineSetter"><code>__defineSetter__</code></a></li>
</ul>
<p>It turns out that in our application we almost never return JSON results with the root object as an array in a GET. So the best fix was generally just to tell the framework that we have examined the risk and determined it returning JSON in this case, by changing code like:</p>
<blockquote><p><code><strong>return </strong>Json(model);</code></p></blockquote>
<p>&#8230;to:</p>
<blockquote><p><code><strong>return </strong>Json(model, JsonRequestBehavior.AllowGet);</code></p></blockquote>
<p>Unfortunately, I had to make this change in a lot of places. Still, I agree with the framework designers: Better safe than sorry.</p>
<h3>JavaScript Files</h3>
<p>The MicrosoftAjax.js, MicrosoftAjax.debug.js, MicrosoftMvcAjax.debug.js, and MicrosoftMvcAjax.debug.js files have all changed for ASP.NET MVC 2. Existing ASP.NET MVC 1.0 projects will have old versions of these files. <del datetime="00">The upgrade instructions in the Release Notes don&#8217;t mention this, but</del> (they do; I just missed it) you should replace these files with the newer versions when upgrading to MVC 2. To do this, create a new MVC 2 project, copy the JavaScript files from the Scripts folder in this new project, and paste them over the existing files in the project you are upgrading.</p>
<h3>ModelBindingContext Changes</h3>
<p>One of the new features of preview 2 is client-side validation and custom metadata providers for validations. In order to implement this feature, some of the implementation details of model binding have changed. This won&#8217;t affect most people, but the fix was a little tricky, and required a good bit of examination of the MVC source code, so I&#8217;ll list it anyway. Prior to preview 2, I had code in a unit test for a custom model binder like this:</p>
<blockquote>
<pre><code>        <strong>internal static </strong>T Bind&lt;T&gt;(<strong>string </strong>prefix, FormCollection collection, ModelStateDictionary modelState) <strong>where </strong>T:<strong>class</strong>
        {
            <strong>var </strong>mbc = <strong>new </strong>ModelBindingContext()
            {
                ModelName = prefix,
                ModelState = modelState,
                ModelType = typeof(T),
                ValueProvider = collection.ToValueProvider()
            };
            IModelBinder binder = <strong>new </strong>MyModelBinder();
            <strong>var </strong>cc = <strong>new </strong>ControllerContext();
            <strong>return </strong>binder.BindModel(cc, mbc) <strong>as </strong>T;
        }
</code></pre>
</blockquote>
<p>With Preview 2, on the other hand, I have to do this:</p>
<blockquote>
<pre><code>        <strong>internal static </strong>T Bind&lt;T&gt;(<strong>string </strong>prefix, FormCollection collection, ModelStateDictionary modelState) <strong>where </strong>T:<strong>class</strong>
        {
            <strong>var </strong>mbc = <strong>new </strong>ModelBindingContext()
            {
                ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(T)),
                ModelName = prefix,
                ModelState = modelState,
                ValueProvider = collection.ToValueProvider()
            };
            IModelBinder binder = <strong>new </strong>MyModelBinder();
            <strong>var </strong>cc = <strong>new </strong>ControllerContext();
            <strong>return </strong>binder.BindModel(cc, mbc) <strong>as </strong>T;
        }
</code></pre>
</blockquote>
<p>Not hard once you know the trick.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38476&amp;akst_action=share-this" onclick="akst_share('38476', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F05%2F38476%2F', 'Updating+to+ASP.NET+MVC+2+Preview+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_38476" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Updating%20to%20ASP.NET%20MVC%202%20Preview%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F05%2F38476%2F" id="akst_email_38476" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Comparing C#, C++, and Delphi (Win32) Generics</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comments</comments>
    <pubDate>Thu, 01 Oct 2009 19:13:29 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38465</guid>
    <description><![CDATA[C#, C++, and Delphi all have a generic type and method language feature. Although all three languages are statically typed, they implement generics in very different ways. I&#8217;m going to give a brief overview of the differences, both in terms of language features and implementation. I presume that Delphi Prism generics work essentially the same [...]]]></description>
      <content:encoded><![CDATA[<p>C#, C++, and Delphi all have a generic type and method language feature. Although all three languages are statically typed, they implement generics in very different ways. I&#8217;m going to give a brief overview of the differences, both in terms of language features and implementation. I presume that Delphi Prism generics work essentially the same as C# generics, which, as you’ll see, is different than Delphi/Win32 generics.</p>
<p>Let me say at the outset that although all three systems work somewhat differently, I don&#8217;t see an overwhelming advantage to any one design. Generally, you can do what you need to do in all three environments. I&#8217;m writing this article not to claim that any one system is better than the others, but to point out some of the subtleties in the implementations.</p>
<p>Before I get started, I&#8217;d like to thank <a href="http://blog.barrkel.com/">Barry Kelly</a> for his useful feedback on my first draft of this article.</p>
<h3>Compiling Instantiations</h3>
<p>Every implementation of generic types works via a two-step process. First, you define a generic type or method with a "placeholder" for a specific type, which will be substituted later on. Later (exactly when depends upon the language), the type is "instantiated." Note that instantiating a generic type is very different from instantiating an object. The former happens within the compiler, whereas the latter happens at runtime.</p>
<p>Instantiation is triggered when some code uses a generic type or method with a specific type parameter, and means that based upon the generic definition and the types or values passed when the generic is used, a specific implementation is substituted in order to allow the generation of machine code. Instantiation is one of the most important differences between real generic types and using non-generic types with casts. In the end, different machine code is generated for instantiations for different type parameters.</p>
<p>In C# and Delphi, there is a language feature which is solely dedicated to implementing generic types and methods. In C++, on the other hand, the "templates" language feature can be used to implement generic types and methods, among many, many other things. It is even possible to do general-purpose programming using templates, which C++ programmers call "<a href="http://www.codeproject.com/KB/cpp/crc_meta.aspx">metaprogramming</a>."</p>
<p>C++ templates require the template source code to be available when the code using the template is compiled. This is because the compiler does not actually compile the template as a separate entity, but rather instantiates it "in-place" and only compiles the instantiation. The C++ compiler is effectively doing code generation, substituting the type parameter (or value) for the placeholder for the type, and generating new code for the instantiation. <strong>Update:</strong> <a title="Audacia Software" href="http://www.audacia-software.de/">Moritz Beutel</a> elaborates on this in <a href="http://blogs.teamb.com/craigstuntz/2009/10/01/38465/#comment-9937">his excellent comment on this post</a>. You should read the full comment, but the short version is that the manner in which templates are compiled can result in errors in the code which uses the template appearing (from compiler error messages), incorrectly, to be errors in the template itself. Moreover, the implementation of most C++ compilers makes this problem even worse than what is necessary in order to implement the C++ standard.</p>
<p>In Delphi and C#, on the other hand, the generic type or method in the code which uses the generic type or method can be compiled separately. Therefore, you can compile a library which contains a generic type, and later on compile an executable which uses a instantiation of that type and has a reference to the binary library, rather than to the source code for the library.</p>
<p>Another way to think of this difference is that in C++, a template will not be compiled at all until it is used. In Delphi and C#, on the other hand, a generic type or method <em>must </em>be compiled before it can be used.</p>
<p>In Delphi, the compiler uses a feature closely related to the method inlining feature. This causes the compiler to store the relevant bits of the abstract syntax tree for the generic type parameter in the compiled DCU. When the code which uses the generic type is compiled, this bit of the abstract syntax tree is read and included in the abstract syntax tree for the code which uses the generic type, so that when machine code is produced, based on the new, “compound” abstract syntax tree, it looks, to the code emitter, like the type was defined with the type parameter "hard coded." Instead of linking to compiled code in the DCU, the code which uses the generic type emits new code for the instantiation into its own DCU.</p>
<p>Because generic instantiation is performed in the same area of the Delphi compiler which does method inlining, there are some limitations on what you can do in a generic method, or a method of a generic type. Like inlined methods, these methods cannot contain ASM. Also, calls to these methods cannot be inlined. These restrictions are limitations of the implementation, not of the language design, and could theoretically be removed in a future version of the compiler.</p>
<p>C# generics use the .NET Framework 2.0+, which has native support for generic types. The C# compiler emits IL which specifies that a generic type should be used, with certain type parameters. The .NET framework implements these types using one instantiation for <em>any </em>reference type, and custom instantiations for value types. (Don’t confuse “instantiation” with “instance” in the preceding sentence; they mean entirely different things in this context. There are usually many instances of one instantiation.) This is because a reference to a reference type is always the same size, whereas value types can be many different sizes. Later, the IL will be JITted into machine code, and, as with compiled C++ or Delphi code, types don’t really exist at the machine code level. In .NET, generic type instantiation and JITting are two distinct operations.</p>
<p>So one important difference in generics implementations is when the instantiation occurs. It occurs very early in C++ compilation, somewhat later for Delphi compilation, and as late as possible for .NET compilation.</p>
<h3>Custom Specializations</h3>
<p>Another very important difference is that C++ allows custom instantiations, called specializations, including specializations by value. With C# and Delphi, on the other hand, the only way to instantiate a generic type is to use that type with an explicit type parameter. The implementation will always be the same, with the exception of the type of the type parameter. Because C++ allows custom instantiations, it is easy for a programmer to write different implementations of a method, for example, for different integer values. Like operator overloading, this is a powerful feature which requires considerable self-restraint to avoid abuse.</p>
<h3>Constraints</h3>
<p>Delphi and C# both have a generic constraint feature, which allows/requires the developer of a generic or method type to limit which type parameter values can be passed. For example, a generic type which needs to iterate over some list of data could require that the type parameter support <code>IEnumerable</code>, in either language. This allows the developer of the generic type to make her intentions for the use of the type very clear. It also allows the IDE to provide code completion/IntelliSense on the type parameter, within the definition of the generic type. Also, it allows a user of the generic type to be confident that they are passing a legal value for the type parameter without having to compile their code to find out.</p>
<p>In C++, on the other hand, there is not presently any such feature. <a href="http://www.devx.com/cplus/Article/42365">A more powerful/complex feature called "concepts" was considered for, but ultimately removed from, C++0x</a>.</p>
<p>An implication of the lack of constraints is that <a href="http://www.ddj.com/cpp/184401971">C++ templates are duck typed</a>. If a generic method calls some method, <code>Foo</code> on a type passed as the generic type parameter, then the template is going to compile just fine so long as the type parameter passed contains some method called <code>Foo</code> with the appropriate signature, no matter where or how it is defined.</p>
<h3>Covariance and Contravariance</h3>
<p>Let’s say I have a function which takes an argument of type <code>IEnumerable&lt;TParent&gt;</code>. Can I pass an argument of type <code>IEnumerable&lt;TChild&gt;</code>; to that function? What if the argument type were <code>List&lt;TParent&gt;</code>; instead of <code>IEnumerable&lt;TParent&gt;</code>? Or what if the generic type was the function <em>result </em>rather than the function argument? The formal names for these problems are <a href="http://blog.barrkel.com/2006/07/covariance-and-contravariance-in-net.html">covariance and contravariance</a>. The precise details are too complicated to explain in this article, but the examples above summarize the most common times you run into the problem.</p>
<p>Delphi generics and C++ templates do not support covariance and contravariance. So the answers to the questions above are no, no, and no, although there are, of course, workarounds, like copying the data into a new list. <a href="http://visualstudiomagazine.com/articles/2009/05/01/generic-covariance-and-contravariance-in-c-40.aspx">In C# 4.0, function arguments and results can be declared covariant or contravariant</a>, so the examples above can be made to work where appropriate. "Where appropriate" involves non-trivial subtleties hinted at above, and exemplified by the fact that <a href="http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx">arrays in .NET have (intentionally) broken covariance</a>. However, the <a href="http://msdn.microsoft.com/en-us/library/dd799517%28VS.100%29.aspx">BCL routines in the .NET Framework 4.0 have been annotated to support covariance and contravariance when appropriate</a>, so developers will benefit from the feature without having to fully understand it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38465&amp;akst_action=share-this" onclick="akst_share('38465', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F01%2F38465%2F', 'Comparing+C%23%2C+C%2B%2B%2C+and+Delphi+%28Win32%29+Generics'); return false;" title="Post to del.icio.us, etc." id="akst_link_38465" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Comparing%20C%23%2C%20C%2B%2B%2C%20and%20Delphi%20%28Win32%29%20Generics&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F10%2F01%2F38465%2F" id="akst_email_38465" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>NDepend Review and Tips</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/24/38398/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/24/38398/#comments</comments>
    <pubDate>Thu, 24 Sep 2009 19:41:30 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38398</guid>
    <description><![CDATA[On and off for the past few months, I&#8217;ve been experimenting with the .NET static analysis tool NDepend. NDepend works somewhat differently than most other static analysis tools I&#8217;ve tried. Notably,

Most tools tend to work on either compiled assemblies or source code. NDepend uses both.
Most tools implement their tests in compiled, executable code. NDepend, on [...]]]></description>
      <content:encoded><![CDATA[<p>On and off for the past few months, I&#8217;ve been experimenting with the .NET static analysis tool NDepend. NDepend works somewhat differently than most other static analysis tools I&#8217;ve tried. Notably,</p>
<ul>
<li>Most tools tend to work on either compiled assemblies or source code. NDepend uses both.</li>
<li>Most tools implement their tests in compiled, executable code. NDepend, on the other hand, uses a proprietary, domain-specific language called CQL.</li>
<li>NDepend can enhance its analysis by importing analysis data from related builds, like NCover, Team System coverage analysis, and can compare multiple builds of the same project.</li>
</ul>
<p>As with other static analysis tools, however, NDepend is designed to be used both within Visual Studio and as part of an automated build/continuous integration process.</p>
<p>NDepend claims to support "<a href="http://www.ndepend.com/FAQ.aspx">any .NET language including C#, VB.NET, MC++ and C++\CLI</a>." To put this claim to the test, I ran it against <a href="http://cc.embarcadero.com/Item/26978">a Delphi Prism application</a>. Indeed, it did produce useful results in the analysis, although there were some quirks. It couldn&#8217;t find the assembly from the solution, but after I located it manually analysis could run. I suspect NDepend doesn&#8217;t parse the source code of Prism applications as it does with C#.</p>
<h3>What NDepend Does</h3>
<p>The name "NDepend" presumably comes from the dependency analysis feature. NDepend will display dependencies between assemblies either as a cross tab or a directed graph. See the website for illustrations of this feature.</p>
<p>NDepend also does static analysis along the same lines as Microsoft FxCop and StyleCop, only in a much more interactive manner. By combining the features I&#8217;ve already mentioned, you can easily ask queries like, "What are the most complex methods I&#8217;ve changed recently which have no unit test coverage?"</p>
<p>All of NDepend&#8217;s features are available in its own GUI application, from the command line, within Visual Studio, and in a custom MS build task. So, as with most static analysis tools, you can integrate NDepend into a continuous build environment in order to set enforceable standards on code complexity and the like.</p>
<h3>Installation</h3>
<p>NDepend does not have an installer. You need to create a folder for the application, and unzip an archive file into that folder. To install the integration with Visual Studio, you click a button in the GUI application, once it&#8217;s running. I find point and click installers a bit more convenient, but it was certainly easy to get the application working.</p>
<h3>Default Analysis of a Do-Nothing Application</h3>
<p>NDepend is quite strict even in its default configuration. For example, I ran it on a do-nothing, "File-&gt;New" ASP.NET MVC 2 Preview 1 application, with no code of my own added. It reported quite a number of warnings.</p>
<p>Many of the warnings were incorrect, because NDepend did not automatically find the System.Web.Mvc assembly, which is not stored along with the rest of the .NET framework, even though it is in the GAC. In general, the current version of NDepend will only find assemblies which are in the solution folder or are in the .NET Framework folders automatically. You should add other folders for referenced assemblies manually, even if those assemblies are GACced. To fix this, I had to do the following steps:</p>
<ol>
<li>Go to the Project Properties tab in the GUI.</li>
<li>Click the "View Folders" button.</li>
<li>Click the "Browse" button and manually locate the folder containing the required assembly.</li>
</ol>
<p>With these steps completed, the quality of the analysis improved quite a lot.</p>
<p>NDepend shows the results in its GUI and also produces an HTML report. The HTML report for the do-nothing application was 14 pages long, and the report for our production web application ran over 50 pages. This can be kind of overwhelming for a new user. The issues flagged in the do-nothing application included (with my comments in parentheses):</p>
<ul>
<li>Methods with &gt; 10 lines of code should be commented. (I disagree; methods should be commented when their intention cannot be made clear in code. This has little relationship to method length and is difficult to impossible to flag with static analysis.)</li>
<li>Types with no state should probably be static. (Worth considering.)</li>
<li>Types with no subtypes could be sealed. (NDepend makes it easy to turn this off for public types.)</li>
<li>Classes with small instance sizes, etc., could be structs. (Maybe, if you want value semantics.)</li>
<li>Avoid namespaces with few types. (This is expected on a File-&gt;New application; would work better in a "real" app. FxCop has the same rule.)</li>
<li>You should&#8217;t have types outside a declared namespace. (I agree.)</li>
<li>Avoid [un] boxing. (I agree; great test!)</li>
<li>Types which "could be internal." (NDepend can&#8217;t pick up instantiation via reflection, making this less useful in the specific case of MVC.)</li>
<li>Fields which are assigned only by the constructors of their types should be marked read-only. (I agree; this is a really useful test.)</li>
<li>Type names should begin with an uppercase letter. The default MVC application includes a type called "_Default".</li>
</ul>
<p>For the sake of comparison, I analyzed the same application using FxCop. This produced 11 warnings, about half correct, and about half incorrect. Incorrect warnings included not recognizing the <acronym title="Three Letter Acronym">TLA</acronym> MVC, asserting that Application_Start should be static, and claiming that the application should target .NET Framework 3.5 SP 1 (as opposed to just 3.5), something which Visual Studio 2008 does not allow. Probably correct warnings included that the application should have the CLSCompliant attribute, and that the _Default type was oddly named.</p>
<h3>Customizing the Analysis For a Real Application</h3>
<p>NDepend&#8217;s use of its CQL language to implement its test makes individual test very easy to customize. For example, our production web application includes the Microsoft DynamicQuery library, which is distributed as a single CS file. Because we included this in one of our assemblies instead of creating a separate assembly for it, NDepend analyzes it along with the rest of our assembly. It contains many long methods, and other things which NDepend does not like, but because this is Microsoft&#8217;s code, and not ours, I would like exclude it from the analysis. So I can, for example, change the test for "method too long" from:</p>
<blockquote>
<pre><span style="color: #008000">// &lt;Name&gt;</span><strong>Methods too big (NbLinesOfCode)</strong><span style="color: #008000">&lt;/Name&gt;
</span><span style="color: #0000ff">WARN</span> <span style="color: #0000ff">IF</span> <span style="color: #000064">Count</span> <span style="color: #000000">&gt;</span> <strong>0</strong> <span style="color: #0000ff">IN</span> <span style="color: #0000ff">SELECT</span> <span style="color: #0000ff">TOP</span> <strong>10</strong> <span style="color: #0000ff">METHODS</span> <span style="color: #0000ff">WHERE</span> <span style="color: #000064">NbLinesOfCode</span> <span style="color: #000000">&gt;</span> <strong>30</strong> <span style="color: #0000ff">ORDER</span> <span style="color: #0000ff">BY</span> <span style="color: #000064">NbLinesOfCode</span> <span style="color: #0000ff">DESC</span><span style="color: #000000">
</span><span style="color: #008000">// METHODS WHERE NbLinesOfCode &gt; 30 are extremely complex and
</span><span style="color: #008000">// should be split in smaller methods
</span><span style="color: #008000">// (except if they are automatically generated by a tool).
</span><span style="color: #008000">// See the definition of the NbLinesOfCode metric here </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbLinesOfCode">http://www.ndepend.com/Metrics.aspx#NbLinesOfCode</a></span></pre>
<p>to:</p>
<pre><span style="color: #0000ff">WARN</span> <span style="color: #0000ff">IF</span> <span style="color: #000064">Count</span> <span style="color: #000000">&gt;</span> <strong>0</strong> <span style="color: #0000ff">IN</span> <span style="color: #0000ff">SELECT</span> <span style="color: #0000ff">TOP</span> <strong>10</strong> <span style="color: #0000ff">METHODS</span>
    <span style="color: #0000ff">WHERE</span> <span style="color: #000064">NbLinesOfCode</span> <span style="color: #000000">&gt;</span> <strong>30</strong>
        <span style="color: #0000ff">AND</span> <span style="color: #000000">!</span><span style="color: #000000">(</span><span style="color: #000064">FullNameLike</span> <span style="color: #a31515">"^System.Linq.Dynamic"</span><span style="color: #000000">)</span> <span style="color: #0000ff">
    ORDER</span> <span style="color: #0000ff">BY</span> <span style="color: #000064">NbLinesOfCode</span> <span style="color: #0000ff">DESC</span></pre>
</blockquote>
<p>What if you don&#8217;t know how to write a regular expression? Well, then you need to <a href="http://www.regular-expressions.info/quickstart.html">learn how to write a regular expression</a>. Regular expressions are the only option for this kind of name matching in NDepend.</p>
<p>It might seem at first that using a proprietary language would be a barrier to using the tool. After all, other tools, like FxCop can be customized using C# and other .NET languages. Doesn&#8217;t a proprietary syntax like CQL discourage customization? Not really, in my experience. The real win of NDepend is that you can customize the rules interactively, within the GUI. In contrast to building a custom FxCop rule and restarting FxCop, this is a huge win, because it encourages the use of ad hoc queries and trial and error to build the ideal heuristic for your application. Coupled with auto complete in the CQL editor, it makes the relatively minor inconvenience of dealing with a proprietary language almost irrelevant. Yes, I would prefer to use LINQ, but the interactivity of CQL is a much bigger win.</p>
<p>However, you don&#8217;t get the same kind of customizability at a global level. You can include and exclude assemblies from analysis globally, but that&#8217;s about it. So while you can include and exclude code based on almost any imaginable criterion at the level of an individual test, I have not found any way to do an exclusion like the one I demonstrate above globally. (Note, however, that in a comment on this blog a week ago, <a href="http://blogs.teamb.com/craigstuntz/2009/09/16/38396/#comments">a member of the NDepend team suggested that features along this line may be coming next year</a>.)</p>
<p>I should add that most static analysis tools seem to work this way. They typically make it fairly easy to include and exclude entire tests or specific tests on specific cases, but don&#8217;t typically include a way to say, "Don&#8217;t run any test on any bit of code which meets the following criteria, ever." So NDepend is no worse than other tools I&#8217;ve used in this regard, and it&#8217;s features to customize individual tests are considerably better than most other tools, although the learning curve is a bit steeper.</p>
<p>Like every static analysis tool I&#8217;ve ever tried, NDepend does not produce useful results for generated code. Since this is not an NDepend-specific issue, I discussed it in <a title="Static Analysis and Generated Code" href="http://blogs.teamb.com/craigstuntz/2009/09/16/38396/">an earlier post</a>, along with some tips for excluding generated code from NDepend&#8217;s analysis.</p>
<h3>Documentation</h3>
<p>The documentation in the NDepend online help is a bit thin. But the authors have written <a title="NDepend Tips and Tricks" href="http://www.ndepend.com/Tips.aspx">a number of informative blog posts</a> on how to use specific features and tips for getting the most out of the tool. Once you realize that these posts exist and know where to find them, it is quite a bit easier to read up on how to use the tool effectively.</p>
<h3>Usability</h3>
<p>I&#8217;m of two, contrasting opinions regarding the usability of NDepend. I found the initial learning curve to be quite steep, and elements of the user interface to be not very discoverable. On the other hand, once I figured out how to use the application, which took me a few weeks (maybe I&#8217;m just slow), I found the application to be very usable, and I could do what I needed to do very quickly. Watching the <a href="http://www.ndepend.com/VisualNDepend.aspx">videos on the NDepend website</a> helps quite a lot in getting over this initial hump. I&#8217;ve also had some e-mail discussions with the makers of the software on how they might improve some of the things this new user found initially confusing in their next release.</p>
<p>For those new to the application, here are some things which may help you get started:</p>
<ul>
<li>The CQL query editor has auto complete, so it&#8217;s fairly easy to customize a query even if you&#8217;re unfamiliar with the language. However, if you intend to do any serious work in CQL, it is worth seeking out and spending some time reviewing the <a href="http://www.ndepend.com/CQL.htm#_Toc225919999">CQL examples on the NDepend website</a>.</li>
<li>After you do an initial analysis, look at the error list before considering the analysis results. Adjust the configuration (by adding assemblies or search directories) to clean up any of the errors before moving on to looking at the analysis results. There are a few valid C# language constructs that NDepend&#8217;s source code parser won&#8217;t recognize. I got a warning from a class constraint on a generic type. I understand this will be fixed in a future version. You can ignore these warnings; they&#8217;re harmless.</li>
<li>Whatever you want to do within the application, the place to start is by selecting the appropriate view configuration from the View menu. So if you want to alter a query to return more specific results, you would select View -&gt; Reset Views to work with the CQL language.</li>
<li>The CQL Query Result tab will display a query, and has been Edit button, you can never added a query in that window. To edit a query, go to the CQL Queries tab, select the query you&#8217;d like to edit, and click the Edit Query button. A new tab will appear which allows you to actually edit query.</li>
<li>When you click on a query in the CQL Queries window, you will only see the results if the query returns any rows. If the query returns no rows, then the results window will not appear.</li>
<li>Whenever you analyze the project in the NDepend GUI, NDepend creates a lengthy HTML report, and opens it in your web browser. But all of the information in the report is also available within the GUI application, as well. So you can see the same information in whichever place is most convenient for you to navigate.</li>
</ul>
<h3>Performance</h3>
<p>NDepend is fast, sometimes surprisingly so, given that it is looking at both binaries and source code. It generally takes less time to run an analysis than it does to compile a solution. I never experienced any performance problems in the NDepend GUI, either.</p>
<h3>Conclusion</h3>
<p>Do you need NDepend? It depends. NDepend will be useful to developers and teams who have a functioning continuous integration process (<a href="http://blogs.teamb.com/craigstuntz/2007/10/30/37765/">and you should</a>) and want to impose standards on this sort of code which can be checked in to the repository. But if you&#8217;re going to go down this road, you should probably start with FxCop, which is free and better known. NDepend, however, can take this kind of analysis much, much farther than would be possible even with custom FxCop rules, like comparing multiple versions of an application and mandating unit test coverage. I also find it much easier to customize.</p>
<p>If you do have an automated build procedure in place and you&#8217;re not already doing static analysis, it&#8217;s time to start! It can be a bit overwhelming to run static analysis for the first time on a legacy project and see hundreds of warnings or errors. But that&#8217;s easy to get over; simply disable all the warnings but one, and start cleaning things up a bit at a time. You can make the analysis stricter as time goes on. You don&#8217;t have to start by fixing everything. Even a few rules in place will prevent new such errors being introduced to the source base.</p>
<p>It will be also useful to developers confronting a large source base for the first time, particularly if there are more than a few assemblies involved.</p>
<p>While NDepend might be useful to a single developer reviewing their own code, and not part of an automated process, I&#8217;ve found that static analysis will really only be used regularly when it is automated. Few developers have the discipline to run static analysis and cleanup any problems uncovered without integrating it into build automation.</p>
<h3>Disclaimer</h3>
<p>This review is based on a review copy supplied by the makers of NDepend. If you think that has colored my impressions of the tool, well, I disagree, but at least you know.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38398&amp;akst_action=share-this" onclick="akst_share('38398', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F24%2F38398%2F', 'NDepend+Review+and+Tips'); return false;" title="Post to del.icio.us, etc." id="akst_link_38398" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=NDepend%20Review%20and%20Tips&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F24%2F38398%2F" id="akst_email_38398" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Leadership Mistake I Keep Making</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/22/38447/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/22/38447/#comments</comments>
    <pubDate>Tue, 22 Sep 2009 19:24:28 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38447</guid>
    <description><![CDATA[I need to teach myself to say "No" in a much more constructive way.]]></description>
      <content:encoded><![CDATA[<p>Jim Holmes gave a very nice presentation on leadership at the last <a href="http://www.colarc.org/">Columbus Architecture Group</a> meeting. He has covered much of the same material in <a title="Leadership 101" href="http://frazzleddad.blogspot.com/2009/01/leadership-101-my-take-on-fundamentals.html">a series of posts which you can read on his blog</a>. Maybe it&#8217;s just the way that I think, but as I listened to him speak, I thought about the question of what I do most poorly in the area of leadership. Or, to put a more positive spin on it, the thing which I could change that would most improve my leadership skills.</p>
<p>I think I know what the answer is. Very often, someone will suggest an approach to a problem which strikes me as technically wrong or otherwise misguided. Like a lot of geeks, I have an almost compulsive desire to do things correctly, especially in areas where (to me, anyway) there is a clear-cut difference between "the right way" and "the wrong way" of doing it. Over and over again, I have said "no" in a way which ranged somewhere between insufficiently respectful and inappropriate.</p>
<p>I think I can explain why I do this (and I&#8217;ll do so below, for anyone who actually cares), but the important part is this: <strong>I need to teach myself to say "No" in a much more constructive way</strong>.</p>
<p>When I hear (what I feel is) a bad idea, I think I have this little moment of panic about the bad idea getting into our code, and having to maintain it for 10 years, because goodness knows I have a lot of bad ideas to maintain in our VCS. It&#8217;s like I&#8217;m worried that simply mentioning the idea will doom it (or us) to implementation, so I went to put the barrier in front of it before it can go any further.</p>
<p>This may accomplish the technical goal, but saying "No" in an unconstructive way is poor leadership. I don&#8217;t want to create a climate where people hesitate to suggest solutions to a problem, because they might be incorrect. Indeed, I learned as least as much, if not more, from my mistakes is from my successes, so discussing a bad idea may contribute as much to a project is discussing a good idea. Rather than just saying, "That won&#8217;t work because&#8230;" I need to help the person who suggested the idea explore its implications and work out the ups and downs on their own.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38447&amp;akst_action=share-this" onclick="akst_share('38447', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F22%2F38447%2F', 'The+Leadership+Mistake+I+Keep+Making'); return false;" title="Post to del.icio.us, etc." id="akst_link_38447" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Leadership%20Mistake%20I%20Keep%20Making&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F22%2F38447%2F" id="akst_email_38447" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>This Blog Is Now (Officially) Free</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/22/38443/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/22/38443/#comments</comments>
    <pubDate>Tue, 22 Sep 2009 18:55:07 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[This Weblog]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38443</guid>
    <description><![CDATA[I&#8217;ve been posting technical articles and source code on this blog for many years now, but I&#8217;ve never formerly specified a license for the material I&#8217;ve posted. Obviously, I wouldn&#8217;t post it if I didn&#8217;t want people to use what I&#8217;ve written, but I understand that my good intentions are not enough to provide the [...]]]></description>
      <content:encoded><![CDATA[<p>I&#8217;ve been posting technical articles and source code on this blog for many years now, but I&#8217;ve never formerly specified a license for the material I&#8217;ve posted. Obviously, I wouldn&#8217;t post it if I didn&#8217;t want people to use what I&#8217;ve written, but I understand that my good intentions are not enough to provide the legal confidence some projects will require to include the code I&#8217;ve demonstrated in their work.</p>
<p>Therefore, I&#8217;ve updated the <a href="http://blogs.teamb.com/craigstuntz/about/">About</a> page to include formal licensing terms. In particular, any source code I&#8217;ve written and posted here is available under the <a href="http://opensource.org/licenses/mit-license.php">MIT license</a>, which should allow you to do almost anything you want to with it, but read the <a href="http://blogs.teamb.com/craigstuntz/about/">About</a> page for the particulars.</p>
<p>Thanks to <a href="http://techencoder.com/">Robert Claypool</a> for pointing this out.</p>
<p>One other bit of news about this site: Readers who prefer to be informed of new posts via Twitter can now <a href="http://twitter.com/craigstuntz">follow the blog there</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38443&amp;akst_action=share-this" onclick="akst_share('38443', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F22%2F38443%2F', 'This+Blog+Is+Now+%28Officially%29+Free'); return false;" title="Post to del.icio.us, etc." id="akst_link_38443" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=This%20Blog%20Is%20Now%20%28Officially%29%20Free&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F22%2F38443%2F" id="akst_email_38443" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Static Analysis and Generated Code</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/16/38396/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/16/38396/#comments</comments>
    <pubDate>Wed, 16 Sep 2009 19:18:53 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38396</guid>
    <description><![CDATA[In recent months, I&#8217;ve been thinking about the problem of static analysis in generated code. Static analysis means using tools like FxCop and NDepend (for .NET apps) lint (for C) and CodeHealer (for Delphi) to find potential problems in your source code.  Generated code is code written not by a human being, but by [...]]]></description>
      <content:encoded><![CDATA[<p>In recent months, I&#8217;ve been thinking about the problem of static analysis in generated code. Static analysis means using tools like FxCop and <a href="http://www.ndepend.com/">NDepend</a> (for .NET apps) <a href="http://en.wikipedia.org/wiki/Lint_%28software%29">lint</a> (for C) and <a href="http://www.socksoftware.com/codehealer.php">CodeHealer</a> (for Delphi) to find potential problems in your source code.  Generated code is code written not by a human being, but by a tool, such as generated classes for a Entity Framework or LINQ to SQL model, an import for a COM type, or code created by a form generator. Static analysis is intended to find code which is either incorrect or difficult to maintain. The issue exists in any environment where generated code and static analysis meet, but it&#8217;s mainly a problem for me personally in C# and Delphi applications.</p>
<h3>A Useful, But Imperfect, Tool</h3>
<p>Static analysis can be incredibly useful. It finds errors in much the same way that compilers report hints and warnings, but at a significantly deeper level. Compilers typically report a hint or a warning only in cases where the compiler is completely certain that there is a problem with the code, like a completely unused variable. Static analysis tools, on the other hand, can report errors in cases where, for example, the code itself might function, but appears to be too complex to be maintainable. Obviously, there is a gray area between maintainable and unmaintainable, and every static analysis tool I have ever tried has returned false positives. FxCop, for example, will complain that an internal type is never instantiated if the only time it is ever instantiated is inside of a LINQ to Entities query; it doesn&#8217;t seem to be able to "see into the Expression."</p>
<h3>For Code Written By Humans Only</h3>
<p>Static analysis is close to useless for generated code, because it is generated by a tool, tends to always function correctly, and is presumably never maintained by humans, at least directly. But generated code tends to really set off alarms on static analysis tools, due to high line counts, cyclomatic complexities, and numbers of parameters, no unit tests, unusual type and member names, etc. In other words, in generated code <em>functionality </em>is much more important than <em>maintainability</em>. But in non-generated code, maintainability is at least as important as functionality. The best solution is to convince your static analysis tool to ignore the generated code altogether, but this is often easier said than done.</p>
<p>When I run FxCop or NDepend against the source code for our commercial applications, for example, they report a large number of errors, with the majority coming from generated code. The reality is that no tool I have used can consistently distinguish between unmaintainable code written by code generators and unmaintainable code written by programmers, automatically. Therefore, in order to get the maximum benefit from static analysis, we have some additional work to do in order to help the tools look at only the code where their analysis will return useful information for developers.</p>
<h3>Excluding Generated Code From Static Analysis</h3>
<p>The .NET framework includes an attribute, <a href="http://msdn.microsoft.com/en-us/library/system.codedom.compiler.generatedcodeattribute.aspx">GeneratedCode</a>, which is intended to tell tools such as FxCop to ignore parts of your code. Also, FxCop has its own attribute, <a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.codeanalysis.suppressmessageattribute.aspx">SuppressMessage</a> which instructs the tool not to report individual messages in specific cases, and individual tests can be turned off. CodeHealer can be told to suppress a certain number of messages, and you can turn individual tests on and off.</p>
<p>Even with these tools, however, the line between generated and non-generated code is not always clear. FxCop, for example, looks only at compiled assemblies, not at source code. If you have a partial class containing both generated code and human-written code, it&#8217;s important to recall that FxCop cannot tell the difference between the parts of the class which came from the generated code file and the parts which came from the non-generated file. The distinction simply does not exist in the compiled assembly, because "partial" classes are combined at compile time by the C# compiler. So you&#8217;re left with the choice of putting the GeneratedCode attribute on the entire class, causing static analysis to miss code you wrote, or not putting it on the entire class, resulting in static analysis errors from the generated code. The best solution is probably to keep any code you write as part of a partial class as simple as possible, such as calls into another class which does the real work. Considering that partial classes are typically used for things like forms, or LINQ to SQL types, this is a good practice anyway.</p>
<p>Code generation can also work by producing IL or assembly directly, without a source file at all. Obviously, tools which look only at source code, like CodeHealer or Microsoft StyleCop will miss this sort of code (which is a good thing) by their very design. But tools which reflect into compiled code will see this sort of code as no different from any other code in the assembly unless they are specifically designed to exclude it.</p>
<p>For example, when you have an anonymous type with a large number of members in C#, the compiler will generate (in IL) a constructor with an equivalent number of arguments. NDepend flags these as excessive numbers of arguments, and, indeed, it would be correct if this were a real method which I had written.</p>
<h3>Improving Heuristics to Avoid False Positives</h3>
<p>NDepend offers an additional means of filtering data. The tool has a domain specific language for querying your source code, called CQL, and you can use this to filter the specific areas analyzed by NDepend. I can modify the NDepend rules by editing the CQL, so I can, for example, exclude the cases I&#8217;ve just described (generated constructors with large numbers of parameters) by changing the default rule for "too many arguments," which looks like this:</p>
<blockquote>
<pre><span style="color: #008000">// &lt;Name&gt;</span><strong>Methods with too many parameters (NbParameters)</strong><span style="color: #008000">&lt;/Name&gt;
</span><span style="color: #0000ff">WARN</span> <span style="color: #0000ff">IF</span> <span style="color: #000064">Count</span> <span style="color: #000000">&gt;</span> <strong>0</strong> <span style="color: #0000ff">IN</span> <span style="color: #0000ff">SELECT</span> <span style="color: #0000ff">TOP</span> <strong>10</strong> <span style="color: #0000ff">METHODS</span> <span style="color: #0000ff">WHERE</span> <span style="color: #000064">NbParameters</span> <span style="color: #000000">&gt;</span> <strong>5</strong> <span style="color: #0000ff">ORDER</span> <span style="color: #0000ff">BY</span> <span style="color: #000064">NbParameters</span> <span style="color: #0000ff">DESC</span><span style="color: #000000">
</span><span style="color: #008000">// METHODS WHERE NbParameters &gt; 5 might be painful to call and might degrade performance.
</span><span style="color: #008000">// You should prefer using additional properties/fields to the declaring type to handle
</span><span style="color: #008000">// numerous states. Another alternative is to provide a class or structure dedicated to
</span><span style="color: #008000">// handle arguments passing (for example see the class System.Diagnostics.ProcessStartInfo
</span><span style="color: #008000">// and the method System.Diagnostics.Process.Start(ProcessStartInfo))
</span><span style="color: #008000">// See the definition of the NbParameters metric here </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbParameters">http://www.ndepend.com/Metrics.aspx#NbParameters</a></span></pre>
</blockquote>
<p>to this:</p>
<blockquote>
<pre><span style="color: #0000ff">WARN</span> <span style="color: #0000ff">IF</span> <span style="color: #000064">Count</span> <span style="color: #000000">&gt;</span> <strong>0</strong> <span style="color: #0000ff">IN</span> <span style="color: #0000ff">SELECT</span> <span style="color: #0000ff">TOP</span> <strong>10</strong> <span style="color: #0000ff">METHODS</span> <span style="color: #0000ff">
    WHERE</span> <span style="color: #000064">NbParameters</span> <span style="color: #000000">&gt;</span> <strong>5</strong> <span style="color: #0000ff">
        <span style="color: #ff0000">AND</span></span><span style="color: #ff0000"> </span><span style="color: #ff0000">!</span><span style="color: #ff0000">IsGeneratedByCompiler</span><span style="color: #0000ff">
    ORDER</span> <span style="color: #0000ff">BY</span> <span style="color: #000064">NbParameters</span> <span style="color: #0000ff">DESC</span></pre>
</blockquote>
<p>&#8230;and the false positives go away. Unfortunately, this only fixes one test. Similar CQL appears in other default NDepend metrics, like this one:</p>
<blockquote>
<pre><span style="color: #008000">// &lt;Name&gt;</span><strong>Quick summary of methods to refactor</strong><span style="color: #008000">&lt;/Name&gt;</span><span style="color: #000000">
</span><span style="color: #0000ff">WARN</span> <span style="color: #0000ff">IF</span> <span style="color: #000064">Count</span> <span style="color: #000000">&gt;</span> <strong>0</strong> <span style="color: #0000ff">IN</span> <span style="color: #0000ff">SELECT</span> <span style="color: #0000ff">TOP</span> <strong>10</strong> <span style="color: #0000ff">METHODS</span> <span style="color: #008000">/*OUT OF "YourGeneratedCode" */</span> <span style="color: #0000ff">WHERE</span><span style="color: #000000"> 

                                           </span><span style="color: #008000">// Metrics' definitions
</span><span style="color: #000000">     </span><span style="color: #000000">(</span><span style="color: #000000">  </span><span style="color: #000064">NbLinesOfCode</span> <span style="color: #000000">&gt;</span> <strong>30</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">              </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbLinesOfCode">http://www.ndepend.com/Metrics.aspx#NbLinesOfCode</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">NbILInstructions</span> <span style="color: #000000">&gt;</span> <strong>200</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">          </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbILInstructions">http://www.ndepend.com/Metrics.aspx#NbILInstructions</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">CyclomaticComplexity</span> <span style="color: #000000">&gt;</span> <strong>20</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">       </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#CC">http://www.ndepend.com/Metrics.aspx#CC</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">ILCyclomaticComplexity</span> <span style="color: #000000">&gt;</span> <strong>50</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">     </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#ILCC">http://www.ndepend.com/Metrics.aspx#ILCC</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">ILNestingDepth</span> <span style="color: #000000">&gt;</span> <strong>4</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">              </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#ILNestingDepth">http://www.ndepend.com/Metrics.aspx#ILNestingDepth</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #ff0000"><strong>NbParameters &gt; </strong><strong>5</strong></span> <span style="color: #0000ff">OR</span><span style="color: #000000">                </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbParameters">http://www.ndepend.com/Metrics.aspx#NbParameters</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">NbVariables</span> <span style="color: #000000">&gt;</span> <strong>8</strong> <span style="color: #0000ff">OR</span><span style="color: #000000">                 </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbVariables">http://www.ndepend.com/Metrics.aspx#NbVariables</a></span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #000064">NbOverloads</span> <span style="color: #000000">&gt;</span> <strong>6</strong> <span style="color: #000000">)</span><span style="color: #000000">                  </span><span style="color: #008000">// </span><span style="color: #008000"><a href="http://www.ndepend.com/Metrics.aspx#NbOverloads">http://www.ndepend.com/Metrics.aspx#NbOverloads</a></span><span style="color: #008000">
</span><span style="color: #000000">     </span><span style="color: #0000ff">AND</span><span style="color: #000000"> 

     </span><span style="color: #008000">// Here are some ways to avoid taking account of generated methods.
</span><span style="color: #000000">     </span><span style="color: #000000">!</span><span style="color: #000000">(</span> <span style="color: #000064">NameIs</span> <span style="color: #a31515">"InitializeComponent()"</span> <span style="color: #0000ff">OR</span><span style="color: #000000">
        </span><span style="color: #008000">// NDepend.CQL.GeneratedAttribute is defined in the redistributable assembly $NDependInstallDir$\Lib\NDepend.CQL.dll
</span><span style="color: #000000">        </span><span style="color: #008000">// You can define your own attribute to mark "Generated".
</span><span style="color: #000000">        </span><span style="color: #000064">HasAttribute</span> <span style="color: #a31515">"OPTIONAL:NDepend.CQL.GeneratedAttribute"</span><span style="color: #000000">)</span></pre>
</blockquote>
<p>These must all be fixed individually. On the other hand, at least they <em>can </em>be fixed by easily changing the heuristics of the rule, instead of by excluding specific cases, as with many other static analysis tools.</p>
<h3>One Time Pain</h3>
<p>The real win from static analysis tools comes from integrating them into an automated build process. Tools like FinalBuilder and MSBuild can easily be configured to run all of the tools mentioned so far. This allows you to fail the build if potentially unmaintainable code is checked in. The first time you use any static analysis tool, you will probably need to spend a substantial effort in order to get the project to the point where it will not fail the build with existing code. This may involve turning off individual rules (you can gradually turn them on later), fixing specific violations, and excluding code such as generated code. You will then need to integrate the tool into your automated build process. This is, in all honesty, a fair bit of work, but it&#8217;s really a one-time pain. After that, the analysis will pay you back for your effort, day in and day out.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38396&amp;akst_action=share-this" onclick="akst_share('38396', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F16%2F38396%2F', 'Static+Analysis+and+Generated+Code'); return false;" title="Post to del.icio.us, etc." id="akst_link_38396" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Static%20Analysis%20and%20Generated%20Code&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F16%2F38396%2F" id="akst_email_38396" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>How to Think Like the Entity Framework Presentation Available for Free Download</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/11/38394/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/11/38394/#comments</comments>
    <pubDate>Fri, 11 Sep 2009 11:19:11 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[CodeRage]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38394</guid>
    <description><![CDATA[My CodeRage presentation, "How to Think Like the Entity Framework (and why you might want to bother learning that in the first place)," is now available for free download.
]]></description>
      <content:encoded><![CDATA[<p>My <a href="http://conferences.embarcadero.com/coderage">CodeRage</a> presentation, "How to Think Like the Entity Framework (and why you might want to bother learning that in the first place)," is now <a href="http://cc.embarcadero.com/Item/27284">available for free download</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38394&amp;akst_action=share-this" onclick="akst_share('38394', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F11%2F38394%2F', 'How+to+Think+Like+the+Entity+Framework+Presentation+Available+for+Free+Download'); return false;" title="Post to del.icio.us, etc." id="akst_link_38394" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=How%20to%20Think%20Like%20the%20Entity%20Framework%20Presentation%20Available%20for%20Free%20Download&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F11%2F38394%2F" id="akst_email_38394" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>How to Customize ASP.NET MVC Authentication</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/09/38390/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/09/38390/#comments</comments>
    <pubDate>Wed, 09 Sep 2009 15:36:02 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38390</guid>
    <description><![CDATA[If you are developing a web application which requires authentication or security features not included in the regular ASP.NET membership feature, you might decide to implement these features yourself. But it seems as if the first instinct of many ASP.NET MVC developers is to do this by customizing their Controllers, because they&#8217;ve decided that AuthorizeAttribute [...]]]></description>
      <content:encoded><![CDATA[<p>If you are developing a web application which requires authentication or security features not included in the regular ASP.NET membership feature, you might decide to implement these features yourself. But it seems as if the first instinct of many ASP.NET MVC developers is to do this by customizing their Controllers, because they&#8217;ve decided that <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx">AuthorizeAttribute</a> can&#8217;t possibly serve their needs. They will decide that the way to do this is to write some sort of parent Controller type which examines the currently logged-in user when an action executes and changes the result of the action based on who they are. Others will try to re-implement AuthorizeAttribute without ever examining the source code for the original.</p>
<p>These are very bad approaches, for two important reasons:</p>
<ol>
<li><strong>They don&#8217;t work.</strong> If your action result is cached by ASP.NET, then <em>the action will not even run </em>the next time it is requested. AuthorizeAttribute handles this correctly. Code you write in a Controller <em>cannot </em>handle this. Code you write in a custom action filter <em>could</em> work, if you cut and paste the implementation from AuthorizeAttribute. But AuthorizeAttribute is unsealed, so why cut and paste, when you can subtype?</li>
<li>The modularity is wrong. You should aim to develop MVC sites which can be used with any authentication (or role) provider, whether it is ASP.NET membership, domain authentication, OpenId, or a custom membership provider. Wiring authentication concerns into a Controller makes this extremely difficult.</li>
</ol>
<p>I&#8217;ve already hinted at the correct solution for the problem: If you cannot find an out of the box membership provider which does what you need, then <a title="Windows Identity Foundation" href="http://www.microsoft.com/forefront/geneva/en/us/">look harder</a>. If you still can&#8217;t find one, <a title="Implementing a Membership Provider" href="http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx">write your own</a>. Here is a <a href="http://www.asp.net/learn/videos/video-189.aspx">video</a> and an <a href="http://www.devx.com/asp/Article/29256">article</a> on how to do it. Similarly, <a title="Implementing a Role Provider" href="http://msdn.microsoft.com/en-us/library/8fw7xh74.aspx">the role provider can also be customized</a>. In other words, the correct extensibility point for membership in an MVC site is exactly the same as the extensibility point for membership in a non-MVC ASP.NET site.</p>
<p>AuthorizeAttribute does a very simple thing in a somewhat complicated way. The simple thing it does is to tie the MVC framework into the existing ASP.NET membership system, which is quite customizable. That&#8217;s why I am skeptical about claims that AuthorizeAttribute can never serve someone&#8217;s needs. The implementation is more complex than one might imagine is required on first consideration because it must both be thread safe and cooperate with caching, which makes attempting to re-invent it at a different level a doubly bad idea.</p>
<p>Although AuthorizeAttribute doesn&#8217;t do very much, you may decide that it&#8217;s specific behavior is not correct for your project. In that case, it is generally a better idea to subtype AuthorizeAttribute instead of re-inventing your own. This allows you to preserve desirable behavior (like cooperating with caching) while customizing the behavior you need. You will need to override the AuthorizeCore method, taking careful note of the comments (in the <a href="http://aspnet.codeplex.com/Wiki/View.aspx?title=MVC">MVC source code</a> for the inherited method) on thread-safety.</p>
<p>One final word about customizing security: Your general approach should be to use proven, off the shelf, actively maintained solutions and customize as little as possible. If the problem you are trying to solve is not strictly security-related (like adding a custom field to a user profile), then do not alter (and potentially compromise) your security in order to solve it. Instead, find a more appropriate solution, like storing the information elsewhere, such as in <a href="http://www.microsoft.com/forefront/geneva/en/us/">an ASP.NET profile</a> or your own DB. <strong>Doing security correctly is hard, and the consequences of small mistakes can be high.</strong> <a href="http://www.cl.cam.ac.uk/~rja14/Papers/satan.pdf">Even experts in the field make mistakes which can take years to uncover</a>. Even if you follow to the letter everything which is known about implementing good security, today, your implementation may be obsolete tomorrow.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38390&amp;akst_action=share-this" onclick="akst_share('38390', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F09%2F38390%2F', 'How+to+Customize+ASP.NET+MVC+Authentication'); return false;" title="Post to del.icio.us, etc." id="akst_link_38390" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=How%20to%20Customize%20ASP.NET%20MVC%20Authentication&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F09%2F38390%2F" id="akst_email_38390" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>How to Think Like the ADO.NET Entity Framework at CodeRage 4</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/09/04/38373/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/09/04/38373/#comments</comments>
    <pubDate>Fri, 04 Sep 2009 21:45:18 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[CodeRage]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38373</guid>
    <description><![CDATA[This coming Wednesday 9 September I&#8217;ll be doing a presentation at the free, online CodeRage 4 conference:
How to Think Like the ADO.NET Entity Framework
(and why you might want to bother learning to do so in the first place)
In order to use the ADO.NET Entity Framework effectively, you must understand its value-based data model, which is [...]]]></description>
      <content:encoded><![CDATA[<p>This coming Wednesday 9 September I&#8217;ll be doing a presentation at the <a href="http://conferences.embarcadero.com/coderage">free, online CodeRage 4</a> conference:</p>
<h3>How to Think Like the ADO.NET Entity Framework</h3>
<p><img style="float: right" src="/files/2009/09/coderagelogo_1956.jpg" alt="" width="196" height="196" />(and why you might want to bother learning to do so in the first place)</p>
<blockquote><p>In order to use the ADO.NET Entity Framework effectively, you must understand its value-based data model, which is distinctly different from the SQL and ORM approaches to representing and querying data. Programmers who approach the Entity Framework as "just another ORM" often find themselves frustrated or disappointed, a common reaction to trying to force a square peg into a round hole. This presentation examines the Entity Data Model in-depth, explaining where it fits into the context of a larger application, and demonstrates different techniques for retrieving and altering data. Also covered are performance considerations and future directions.</p></blockquote>
<p>Sound like something you&#8217;d like to learn about? The conference is free, but <a href="https://www124.livemeeting.com/lrs/advancedsw_ccc/Registration.aspx?pageName=1694szd61kc6s3vx">you must register to attend</a>. I&#8217;ll be on at <a href="http://www.timeanddate.com/worldclock/converter.html?year=2009&amp;month=9&amp;day=9&amp;hour=17&amp;min=0&amp;sec=0&amp;p1=283&amp;p2=805">5:00 PDT; you can convert that to your local time</a>.</p>
<p>Embarcadero has me in the <a href="http://www.embarcadero.com/products/delphi-prism">Delphi Prism</a> track, but my examples will be in C#.</p>
<p>If .NET&#8217;s not your cup of tea, there are <a href="http://conferences.embarcadero.com/coderage/sessions">plenty of other sessions</a> you can join.</p>
<p><strong>Update:</strong> The conference is over, but you can <a href="http://cc.embarcadero.com/Item/27284">download a recording of my session</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38373&amp;akst_action=share-this" onclick="akst_share('38373', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F04%2F38373%2F', 'How+to+Think+Like+the+ADO.NET+Entity+Framework+at+CodeRage+4'); return false;" title="Post to del.icio.us, etc." id="akst_link_38373" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=How%20to%20Think%20Like%20the%20ADO.NET%20Entity%20Framework%20at%20CodeRage%204&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F09%2F04%2F38373%2F" id="akst_email_38373" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>On That Delphi 7 Virus and Ken Thompson&#8217;s Turing Award Speech</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/08/20/38361/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/08/20/38361/#comments</comments>
    <pubDate>Thu, 20 Aug 2009 15:38:16 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[ACM]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38361</guid>
    <description><![CDATA[In 1984, Ken Thompson, the operating system and programming language pioneer, received the ACM&#8217;s Turing Award. In his short, highly-readable Turing Award speech, he describes "the cutest program I ever wrote." He notes that because the C compiler is written in C, it is possible to alter the source code maliciously to produce a malicious [...]]]></description>
      <content:encoded><![CDATA[<p>In 1984, Ken Thompson, the operating system and programming language pioneer, received the ACM&#8217;s Turing Award. In <a title="Reflections On Trusting Trust" href="http://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf">his short, highly-readable Turing Award speech</a>, he describes "the cutest program I ever wrote." He notes that because the C compiler is written in C, it is possible to alter the source code maliciously to produce a malicious compiler executable. The malicious code can then be removed from the C source, and the original code recompiled. The malicious code remains in the "new" executable, however, because it was prouced by the trojaned compiler.</p>
<p>If you can persuade someone to use your modified compiler, or if you can modify the compiler on their machine, then you can infect the executables they produce, even if they recompile the compiler itself from source code! If that seems unlikely or difficult, read the whole paper. It&#8217;s easier than you think. Thompson concludes:</p>
<blockquote><p>The moral is obvious. You can&#8217;t trust code that you did not totally create yourself. (Especially code from companies that employ people like me.) No amount of source-level verification or scrutiny will protect you from using untested code. In demonstrating the possibility of this kind of attack, I picked on the C compiler. I could have picked on any program-handling program such as an assembler, a loader, or even hardware microcode. As the level of program gets lower, these bugs will be harder and harder to detect. A well-installed microcode bug will be almost impossible to detect.</p></blockquote>
<p>Now it seems that <a title="Delphi developer virus exposes weakness in anti-virus defences" href="http://www.itwriting.com/blog/1717-delphi-developer-virus-exposes-weakness-in-anti-virus-defences.html">somebody has actually gone and done this with old versions of Delphi</a>. Frankly, I&#8217;m surprised it took so long. Perhaps this is just the first time we&#8217;ve noticed. But the problem described by Thompson is so insidious that in the quarter century since he gave his address (which really just gave additional prominence to an issue discovered decades before that) it&#8217;s almost remarkable that this technique is not more widespread. It&#8217;s also interesting that this specific case is relatively innocuous; the virus does nothing more than reproduce itself, and only affects a very old compiler. Is this a test shot? Someone whose curiosity got the better of them?</p>
<p>I don&#8217;t know. But the historical perspective is clear: This is not about Delphi, and it&#8217;s not about the malware of the week. It&#8217;s an old question of trust becoming new again.</p>
<p><a title="Countering Trusting Trust through Diverse Double-Compiling" href="http://www.acsa-admin.org/2005/abstracts/47.html">Here is one proposal for countering these attacks</a>. Interestingly, the technique can sometimes find unintended compiler bugs, as well. They can be hard to distinguish sometimes!</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38361&amp;akst_action=share-this" onclick="akst_share('38361', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F20%2F38361%2F', 'On+That+Delphi+7+Virus+and+Ken+Thompson%26%238217%3Bs+Turing+Award+Speech'); return false;" title="Post to del.icio.us, etc." id="akst_link_38361" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=On%20That%20Delphi%207%20Virus%20and%20Ken%20Thompson%26%238217%3Bs%20Turing%20Award%20Speech&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F20%2F38361%2F" id="akst_email_38361" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>InterBase 2009 Hotfix Update 3</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/08/19/38359/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/08/19/38359/#comments</comments>
    <pubDate>Wed, 19 Aug 2009 13:38:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38359</guid>
    <description><![CDATA[InterBase 2009 Hotfix Update 3 (version 9.0.3.437) is out. See the readme for the full list of bug fixes.
]]></description>
      <content:encoded><![CDATA[<p>InterBase 2009 Hotfix Update 3 (version 9.0.3.437) is out. See <a title="InterBase 2009 Hotfix Update 3 Readme" href="http://edn.embarcadero.com/article/39821">the readme</a> for the full list of bug fixes.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38359&amp;akst_action=share-this" onclick="akst_share('38359', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F19%2F38359%2F', 'InterBase+2009+Hotfix+Update+3'); return false;" title="Post to del.icio.us, etc." id="akst_link_38359" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=InterBase%202009%20Hotfix%20Update%203&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F19%2F38359%2F" id="akst_email_38359" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero Change Manager To Support InterBase, Firebird</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/08/13/38352/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/08/13/38352/#comments</comments>
    <pubDate>Thu, 13 Aug 2009 18:15:11 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38352</guid>
    <description><![CDATA[Embarcadero&#8217;s Change Manager will support InterBase (and Firebird) this fall, according to PM Gordan Lucas. He even has video evidence!
Change Manager 5.1.1 will add support for InterBase 2007 and 2009 databases to: compare, version, and synchronize schemas; compare, synchronize, move, and mask data; and compare, version, and monitor version configurations for compliance and tracking.
And for [...]]]></description>
      <content:encoded><![CDATA[<p>Embarcadero&#8217;s <a href="http://www.embarcadero.com/embarcadero-change-manager">Change Manager</a> will support InterBase (and Firebird) this fall, <a href="http://gordon-lucas.blogspot.com/2009/08/change-manager-and-interbase.html">according to PM Gordan Lucas</a>. He even has video evidence!</p>
<blockquote><p>Change Manager 5.1.1 will add support for InterBase 2007 and 2009 databases to: compare, version, and synchronize schemas; compare, synchronize, move, and mask data; and compare, version, and monitor version configurations for compliance and tracking.</p>
<p>And for any Firebird SQL users out there, you can join the party too because Change Manager will support versions 1.5 and 2.0 of that database. Move your data to and from any platform we support and move and compare schemas between Firebird and InterBase.</p></blockquote>
<p>Also, it&#8217;s worth noting <a href="http://etnaweb04.embarcadero.com/bogo-info/">you can get Change Manager for free with the purchase of another Embarcadero tool</a>, including Delphi or InterBase.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38352&amp;akst_action=share-this" onclick="akst_share('38352', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F13%2F38352%2F', 'Embarcadero+Change+Manager+To+Support+InterBase%2C+Firebird'); return false;" title="Post to del.icio.us, etc." id="akst_link_38352" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero%20Change%20Manager%20To%20Support%20InterBase%2C%20Firebird&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F13%2F38352%2F" id="akst_email_38352" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>2D Goggles - Babbage and Lovelace</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/08/13/38348/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/08/13/38348/#comments</comments>
    <pubDate>Thu, 13 Aug 2009 15:32:05 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38348</guid>
    <description><![CDATA[Warning: The following comic has been demonstrated to severely lower developer productivity upon first introduction.
Sydney Padua has done the impossible: Created a programming comic which I like as much as XKCD. You can start at the beginning or read the latest, thrilling episode. She also did a special for the BBC. Navigation is a bit [...]]]></description>
      <content:encoded><![CDATA[<blockquote><p>Warning: The following comic has been demonstrated to severely lower developer productivity upon first introduction.</p></blockquote>
<p>Sydney Padua has done the impossible: Created a programming comic which I like as much as <a href="http://xkcd.com">XKCD</a>. You can <a title="Ada Lovelace - The Origin!" href="http://sydneypadua.com/2dgoggles/lovelace-the-origin-2/">start at the beginning</a> or read <a title="Lovelace and Babbage vs. the Client" href="http://sydneypadua.com/2dgoggles/lovelace-and-babbage-vs-the-client-pt-2/">the latest, thrilling episode</a>. She also did <a title="Techlab" href="http://news.bbc.co.uk/2/hi/technology/8139075.stm">a special for the BBC</a>. Navigation is a bit awkward (look for the "next" and "back" links above each post), but entirely worth the effort.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38348&amp;akst_action=share-this" onclick="akst_share('38348', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F13%2F38348%2F', '2D+Goggles+-+Babbage+and+Lovelace'); return false;" title="Post to del.icio.us, etc." id="akst_link_38348" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=2D%20Goggles%20-%20Babbage%20and%20Lovelace&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F08%2F13%2F38348%2F" id="akst_email_38348" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Columbus Give Camp</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/07/21/38329/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/07/21/38329/#comments</comments>
    <pubDate>Tue, 21 Jul 2009 14:32:50 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38329</guid>
    <description><![CDATA[This past weekend I, along with around 50 other local geeks, volunteered three days of my time to build web applications for eight different Columbus-area nonprofits. Columbus Give Camp is based on a similar series of events in Michigan. The Columbus Give Camp was hosted by Quick Solutions, who, conveniently, are located five floors above [...]]]></description>
      <content:encoded><![CDATA[<p>This past weekend I, along with around 50 other local geeks, volunteered three days of my time to build web applications for eight different Columbus-area nonprofits. <a href="http://www.columbusgivecamp.org/">Columbus Give Camp</a> is based on <a href="http://michigangivecamp.org/">a similar series of events in Michigan</a>. The Columbus Give Camp was hosted by <a href="http://www.quicksolutions.com/">Quick Solutions</a>, who, conveniently, are located five floors above my own office. The event was a huge success. I&#8217;m particularly proud of the work my team did, taking the project from nothing to live and in production in just a few days work.</p>
<p>The Give Camp organizers found charities who needed web development donations and split the registered developers into teams based upon skill sets and organization needs. I was assigned to the team for the <a href="http://www.ficccs.com/">Shiloh Family Institute College Choir Concert Series</a>, a small organization which sponsors a series of gospel choir performances once a year. They needed a web site to promote the organization, list upcoming events, allow their patrons to register for e-mail alerts of scheduled concerts, and think their donors. Critically, the site had to be easy to maintain for administrators without computer expertise. My team included Brahma Ghosh, <a href="http://geekswithblogs.net/bjackett/">Brian Jackett</a>, Joel Broughton, <a href="http://josephours.blogspot.com/">Joseph Ours</a>, and Peter Vasys. Prior to the start of Give Camp, Brahma, the project manager, met with representatives of the organization and produced a mockup of each page we would build in the site.</p>
<p>We decided to build the sites using (non-MVC) ASP.NET, because that was the "least common denominator" of the skill sets of our team members. The requirements for the site specified displaying 10-20 concerts and around 10 sponsors. In view of the tiny data set and the emphasis on ease-of-use for the folks who will be maintaining the site, we decided against using a database or off-the-shelf content management system. Instead, we built the site such that the content areas would simply be editable in a WYSIWYG editor if you are logged into the site. So the site maintainers only needed to be instructed as to how to log in, and the rest is obvious.</p>
<p>Here is a part of what a logged-in user sees on the site homepage; you can compare that with <a href="http://www.ficccs.com/">the production site</a> in order to see the difference.</p>
<div id="attachment_38330" class="wp-caption aligncenter" style="width: 510px"><a href="/files/2009/07/sficccs_1512.png"><img src="/files/2009/07/sficccs_1512.png" alt="WYSIWYG editor on site home page" width="500" height="259" /></a><p class="wp-caption-text">WYSIWYG editor on site home page</p></div>
<p>At the beginning of Friday night, we met our clients, discussed the requirements for the project, settled on which technology we would use to build the site, and got to work. One of the first things we needed to do was to register a domain name and secure hosting so that the site could go live on Sunday. Also, we set up a Subversion repository on <a href="http://www.assembla.com/">assembla.com</a>. Then we split up the work and started writing code. The project manager created a solution for the project and checked it into subversion. I started creating repositories for the data which would be editable on the site. Because each dataset would only hold 10 through 20 records maximum, we decided to use XML files instead of a database to hold the data. Performance is not a problem with such a small dataset, and using files instead of a database allows non-technical users to easily move the site from one hosting provider to another. Also, we used the repository pattern, so it&#8217;s possible to switch out the storage without changing a line of web client code in the event the site ever grows beyond its current scale. The first thing I did was check in the public interfaces for the repositories so that the people creating the web pages could start work before I was done with the implementation. Other team members created web pages, started the site design, and began implementing a Google Maps feature on the "upcoming concert" page.</p>
<p>We wrote unit tests for all of the repositories in the site. In view of the very short amount of time we had to develop the site, that might seem surprising. In fact, however, writing unit tests allowed us to test the repository functionality before the web pages which used the repositories were finished, so even though it was a little extra work, it improved our ability to work concurrently.</p>
<p>I went home to get some sleep around 2 a.m. Friday night, but some people worked through the whole night. The Give Camp organizers supplied us with food, caffeine, and entertainment. I spent most of Saturday implementing a feature to allow the site maintainers to add and remove sponsors, including a feature to upload sponsor logos and thumbnail them to the correct size for the site. By the end of Saturday, just after midnight, all of the major features of the site except for the Google Maps were working, and we were down to fixing bugs and typos. A pleasant surprise for me was that the food provided was consistently good and occasionally even healthy; the Give Camp organizers had recruited some local restaurants as <a href="http://www.columbusgivecamp.org/GiveCamp/Home/Sponsor">sponsors</a>, and a grateful charity brought in some large containers of fruit.</p>
<p>Incidentally, there are some <a href="http://www.flickr.com/photos/tags/columbusgivecamp2009/">photos of Give Camp on Flickr</a>.</p>
<p>We spent the first half of Sunday cleaning up defects, and the second half testing and fixing typos in the content. Some of the other team members implemented the Google Maps feature in two different ways in order to be sure that we would have at least one which worked before we deployed the site to production.</p>
<p>At 4:00 p.m. on Sunday, all eight teams presented their work. There was a real diversity of projects. In our case, we built a simple site from scratch and finished it the same weekend. Other teams added new features to existing sites. One team was given three or four different sites using different technologies with the instructions to make them have a common look and feel. Every one of the clients appeared completely delighted with the end results.</p>
<p>Whenever I read "studies" which claim that the majority of software projects fail, I have to balance these claims against my own personal experience, which demonstrates that projects can be successful even with very little time and team members who have never spoken to each other before the instant the project begins. So why did this project work out so well?</p>
<ul>
<li>Our project manager did excellent work up front with the client, so we knew exactly what we needed to build.</li>
<li>The client had a good sense of priorities for the project.</li>
<li>The team was highly motivated. We were all participating by choice. The Give Camp organizers kept the emphasis on fun. The deadline was challenging, but realistic.</li>
<li>The Give Camp organizers did a great job splitting up the teams. We had people with project management skills, design skills, and development skills.</li>
<li>We used off-the-shelf functionality where appropriate. For example, the mailing list registration is handled via the <a href="http://www.mailchimp.com/">MailChimp</a> API. The map feature is done with <a href="http://code.google.com/apis/maps/">Google Maps</a>. Event photos are hosted on Flickr. We used their API to show a single image when there was only one image of an event available, and a slideshow when multiple images were available.</li>
<li>We built only what was needed. Using an off-the-shelf CMS would have delivered more features, but at the cost of being difficult for the client to maintain, both in terms of the user interface and a database on the back end. The client made it clear that ease-of-use was paramount, and we stuck to that.</li>
<li>There was no dead weight on the team. <a href="http://elegantcode.com/2009/01/14/bad-apple-behaviors/">A single, unmotivated developer can slow down an entire team</a>. Since everyone was there by choice, and everyone was qualified for the work, we didn&#8217;t have to deal with any problem team members.</li>
<li>We had our choice of technologies, so we could choose a platform with which everyone on the team had at least some familiarity.</li>
</ul>
<p>Give Camp was the most fun I&#8217;ve had coding in some time, even though (non-MVC) ASP.NET is not my preferred platform. The emphasis on fun, the opportunity to try things outside of my comfort zone, and the excellent team atmosphere made it a great experience.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38329&amp;akst_action=share-this" onclick="akst_share('38329', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F21%2F38329%2F', 'Columbus+Give+Camp'); return false;" title="Post to del.icio.us, etc." id="akst_link_38329" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Give%20Camp&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F21%2F38329%2F" id="akst_email_38329" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Skip(0) in LINQ and Testing</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/07/07/38326/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/07/07/38326/#comments</comments>
    <pubDate>Tue, 07 Jul 2009 19:53:34 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38326</guid>
    <description><![CDATA[A couple of weeks ago, I wrote In LINQ, Beware of Skip(0). In that post, I observed that calling Skip(0) on a query result in LINQ, which has no effect on the dataset returned, imposes a performance penalty with at least some LINQ providers. At the time I commented that there might be some desirable [...]]]></description>
      <content:encoded><![CDATA[<p>A couple of weeks ago, I wrote <a href="http://blogs.teamb.com/craigstuntz/2009/06/10/38313/">In LINQ, Beware of Skip(0)</a>. In that post, I observed that calling Skip(0) on a query result in LINQ, which has no effect on the dataset returned, imposes a performance penalty with at least some LINQ providers. At the time I commented that there might be some desirable behavior of this that I had missed. Sure enough, one of the developers on the LINQ to SQL team <a href="http://blogs.teamb.com/craigstuntz/2009/06/10/38313/#comment-7652">noted in comments that Skip(0) will cease to be a no-op in LINQ to SQL in .NET 4.0</a>, and supplied a perfectly reasonable explanation for the change.</p>
<p>Given that calling Skip(0) introduces a performance penalty, but there is a reason for introducing that penalty, should we avoid making this call? The short answer is yes, the performance improvement is worth it, but don&#8217;t forget the rule that you should have one test case for every conditional in your code. This rule is generally applied to unit testing, but in this case the appropriate test is an integration test, since you need to be sure that the LINQ provider will perform acceptably and not fail altogether when you fetch the data for the second page, which is now an entirely different query than that used to retrieve the data for the first page.</p>
<p>When I first observed the issue, I was happy to discover that I could make the query which fetches data for the first page of a result set (which happens to be the page which users most commonly request) 10 times faster. Of course, the other way to look at this is that the query that fetches data for the second and all subsequent pages is 10 times slower than the query which fetches data for the first page. Again, given that the first page is displayed much more frequently, that&#8217;s not necessarily a bad thing, <em>as long as it doesn&#8217;t catch you by surprise</em>. Indeed, calling Skip(n), where n &gt; 0, and getting your results not quite as quickly as if you had not called Skip(n) at all is actually the best case; the worst possible case is that the LINQ provider will generate invalid SQL and the query will fail.</p>
<p>Note that it is especially difficult to ensure complete integration testing coverage as you introduce more and more ways that the user can shape a result set. If the user can change the sort order, enter a variety of search queries, etc., it&#8217;s a safe bet that every combination of these options will produce a different query with different performance characteristics. Avoiding calling Skip(0), in other words, does not increase the number of integration test cases for a particular list of data by one; it doubles it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38326&amp;akst_action=share-this" onclick="akst_share('38326', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F07%2F38326%2F', 'Skip%280%29+in+LINQ+and+Testing'); return false;" title="Post to del.icio.us, etc." id="akst_link_38326" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Skip%280%29%20in%20LINQ%20and%20Testing&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F07%2F38326%2F" id="akst_email_38326" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Kahn Racing Again</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/07/06/38324/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/07/06/38324/#comments</comments>
    <pubDate>Mon, 06 Jul 2009 19:10:32 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38324</guid>
    <description><![CDATA[Philippe Kahn is once again competing in the Transpac (sailboat) Ocean race.
]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.pegasus.com/log.htm">Philippe Kahn is once again competing</a> in the Transpac (sailboat) Ocean race.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38324&amp;akst_action=share-this" onclick="akst_share('38324', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F06%2F38324%2F', 'Kahn+Racing+Again'); return false;" title="Post to del.icio.us, etc." id="akst_link_38324" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Kahn%20Racing%20Again&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F07%2F06%2F38324%2F" id="akst_email_38324" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Columbus Give Camp</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/06/16/38321/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/06/16/38321/#comments</comments>
    <pubDate>Tue, 16 Jun 2009 11:55:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38321</guid>
    <description><![CDATA[If you&#8217;re a geek in the Central Ohio area, please consider volunteering for Columbus Give Camp, if your schedule permits.
]]></description>
      <content:encoded><![CDATA[<p>If you&#8217;re a geek in the Central Ohio area, please consider volunteering for <a href="http://www.columbusgivecamp.org/GiveCamp/">Columbus Give Camp</a>, if your schedule permits.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38321&amp;akst_action=share-this" onclick="akst_share('38321', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F16%2F38321%2F', 'Columbus+Give+Camp'); return false;" title="Post to del.icio.us, etc." id="akst_link_38321" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Give%20Camp&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F16%2F38321%2F" id="akst_email_38321" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>In LINQ, Beware of Skip(0)</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/06/10/38313/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/06/10/38313/#comments</comments>
    <pubDate>Wed, 10 Jun 2009 19:29:44 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38313</guid>
    <description><![CDATA[Calling IQueryable&#60;T&#62;.Skip(0) seems like it should be "free." In other words, since it will have no effect on the resulting data, there should be little to no performance cost for calling it. But this is demonstrably not true in LINQ to Entities, and it occurs to me that LINQ providers are not required to optimize [...]]]></description>
      <content:encoded><![CDATA[<p>Calling <code>IQueryable&lt;T&gt;.Skip(0)</code> <em>seems</em> like it should be "free." In other words, since it will have no effect on the resulting data, there should be little to no performance cost for calling it. But this is demonstrably not true in LINQ to Entities, and it occurs to me that LINQ providers are not required to optimize it away. Therefore, it is probably a good idea to avoid making such a call at all, so that you do not have to concern yourself with whether the provider will generate a slower query if you do it.</p>
<p>Unfortunately, it is not just your own code you need to be concerned with. It turns out that some fairly popular LINQ helpers do this. For example, <a href="http://blog.wekeroad.com/blog/aspnet-mvc-pagedlistt/">Rob Connery&#8217;s PagedList&lt;T&gt;</a> type does it:</p>
<blockquote>
<pre><code><strong>public </strong>PagedList(IQueryable&lt;T&gt; source, <strong>int</strong> index, <strong>int</strong> pageSize)
{
    <strong>this</strong>.TotalCount = source.Count();
    <strong>this</strong>.PageSize = pageSize;
    <strong>this</strong>.PageIndex = index;
    <strong>this</strong>.AddRange(source.Skip((index - 1) * pageSize).Take(pageSize).ToList());</code></pre>
</blockquote>
<p>Index, in this code, is the 1-based page you&#8217;d like to display. When index is 1, the code calls Skip(0), and you get less efficient SQL. Fixing the problem is quite simple:</p>
<blockquote>
<pre><code>    <strong>this</strong>.PageIndex = index;
    var pageData = index &gt; 1 ?
        source.Skip((index - 1) * pageSize).Take(pageSize) : source.Take(pageSize);
    this.AddRange(pageData.ToList());</code></pre>
</blockquote>
<p>Naturally, this only optimizes SQL generation for the first page of results, but since this is by far the most common page a user might display, it can net you a substantial win in server performance.</p>
<p><a href="http://www.squaredroot.com/2008/07/08/PagedList-Strikes-Back/">Troy Goode&#8217;s updated PagedList type</a>, which I have recommended in the past (and still do, with this tweak!), has the same problem. The solution is almost identical, although Troy&#8217;s type is 0-based rather than 1-based. <strong>Update:</strong> <a href="http://pagedlist.codeplex.com/">Troy has now posted an update</a> containing this fix, among many other changes.</p>
<p>The root of the problem in the SQL generation is that when you call Skip(0), LINQ to Entities, in at least some cases, generates SQL like this:</p>
<blockquote><p><code>)  <strong>AS </strong>[Project3]<br />
<strong>WHERE </strong>[Project3].[row_number] &gt; 0<br />
<strong>ORDER BY</strong> [Project3].[TimeRecordDate] <strong>DESC</strong></code></p></blockquote>
<p>The reference to <code>row_number</code> can have a substantial performance impact. In one case I tried with a SQL Server table containing just over 1 million rows, a simple query ran with sub-second performance without this WHERE clause, and over 4 seconds with the WHERE clause, even though the result set was exactly the same.</p>
<p>Now, is this a bug in LINQ to Entities? Or LINQ itself? It&#8217;s hard to say. Both frameworks are doing exactly what you tell them to, even though it doesn&#8217;t make a lot of sense. It seems like a missed opportunity for optimization, but I&#8217;m open to the possibility that there might be some desirable effect of this that I have simply missed. For my own purposes, I am content to simply not call Skip(0) at all.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38313&amp;akst_action=share-this" onclick="akst_share('38313', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F10%2F38313%2F', 'In+LINQ%2C+Beware+of+Skip%280%29'); return false;" title="Post to del.icio.us, etc." id="akst_link_38313" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=In%20LINQ%2C%20Beware%20of%20Skip%280%29&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F06%2F10%2F38313%2F" id="akst_email_38313" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Early Turbo Pascal History on Hanselminutes</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/14/38310/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/14/38310/#comments</comments>
    <pubDate>Thu, 14 May 2009 17:27:45 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38310</guid>
    <description><![CDATA[In the most recent episode of Hanselminutes, Scott chats with founders of Mustang Software (creators of Wildcat! BBS) Jim Harrer and Scott Hunter about the BBS era. Wildcat! was written in Turbo Pascal, and Harrer and Hunter state that it was one of the first major applications developed in that language. In the first part [...]]]></description>
      <content:encoded><![CDATA[<p>In the most recent episode of Hanselminutes, <a href="http://www.hanselminutes.com/default.aspx?showID=179">Scott chats with founders of Mustang Software (creators of Wildcat! BBS) Jim Harrer and Scott Hunter about the BBS era</a>. Wildcat! was written in Turbo Pascal, and Harrer and Hunter state that it was one of the first major applications developed in that language. In the first part of the show, they discuss going to California to meet with the Turbo Pascal team, visiting Anders Hejlsberg&#8217;s house, and more early history.</p>
<p>It&#8217;s worth a listen if you&#8217;re interested in the history of the product which started Borland and evolved into Delphi.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38310&amp;akst_action=share-this" onclick="akst_share('38310', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F14%2F38310%2F', 'Early+Turbo+Pascal+History+on+Hanselminutes'); return false;" title="Post to del.icio.us, etc." id="akst_link_38310" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Early%20Turbo%20Pascal%20History%20on%20Hanselminutes&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F14%2F38310%2F" id="akst_email_38310" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using DayPilot with ASP.NET MVC</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/12/38297/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/12/38297/#comments</comments>
    <pubDate>Tue, 12 May 2009 12:45:31 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38297</guid>
    <description><![CDATA[I&#8217;m going to demonstrate how to use the open-source DayPilot Lite calendar control in an ASP.NET MVC application. I will discuss the capabilities of the control and consider the general problem of how to use controls designed for "plain" ASP.NET in MVC applications. I&#8217;m including a demo solution which you can download and run yourself.
Download [...]]]></description>
      <content:encoded><![CDATA[<p>I&#8217;m going to demonstrate how to use the open-source <a href="http://www.daypilot.org/daypilot-lite.html">DayPilot Lite calendar control</a> in an ASP.NET MVC application. I will discuss the capabilities of the control and consider the general problem of how to use controls designed for "plain" ASP.NET in MVC applications. I&#8217;m including a demo solution which you can download and run yourself.<a href="/files/2009/05/daypilot_1277.zip"></a></p>
<p><strong>Download the demo solution: </strong><a href="/files/2009/05/daypilot_1277.zip">DayPilot ASP.NET MVC demo</a></p>
<p>We needed a calendar control for an ASP.NET MVC application. In particular, we needed a control which would show a number of events and when they occur within a particular day, "Outlook-style." I&#8217;ll include a screenshot of the demo application here, since it&#8217;s the best way to explain the type of control we were looking for:</p>
<div id="attachment_38298" class="wp-caption aligncenter" style="width: 295px"><a href="/files/2009/05/daypilot_1274.png"><img src="/files/2009/05/daypilot_1274-285x300.png" alt="DayPilot example" width="285" height="300" /></a><p class="wp-caption-text">DayPilot example</p></div>
<h3>Possible Alternatives to DayPilot</h3>
<p>In my experience, the type of control which works best with ASP.NET MVC is a control which is completely ignorant of ASP.NET, and all the <a href="http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/">lies such as ViewState and postbacks</a> which accompany it. In particular, I&#8217;ve had a good deal of success with controls designed for the jQuery JavaScript framework, which is included, by default, with ASP.NET MVC applications. Unfortunately, I was unable to find a jQuery control which data what we needed. The closest I found was <a href="http://www.bytecyclist.com/projects/jmonthcalendar/">jMonthCalendar</a> which cannot display a single day in the manner illustrated above. I would still prefer a jQuery-based solution if one ever turns up.</p>
<p>I did, however, find a couple of controls designed for "plain" ASP.NET which, from an end-user point of view, it exactly what we needed. One was the DayPilot control illustrated above, the other was <a href="http://www.telerik.com/products/aspnet-ajax/scheduler.aspx">the scheduler component included with Telerik&#8217;s control suite</a>. Telerik&#8217;s control claims some support for MVC, but this is really limited to loading calendar data asynchronously, which was not actually what we wanted to do. Also, Telerik&#8217;s control can only be purchased as part of their suite, which is rather expensive if you only need the calendar/scheduler control. Paying for the entire suite would not be a problem for us if it was filled with controls we needed, designed for the environment (MVC) we use. While Telerik seems serious about supporting MVC, they are in the early stages right now, so it is difficult to justify paying for a large suite in order to get a single control, which I would have to use in a mostly-unsupported way. The Telerik control has many more features than the DayPilot control, and, in my opinion, looks a little nicer.</p>
<p>The DayPilot calendar is available in two different editions. There is an open source edition, which is free, and a non-open-source edition, which <a href="http://www.daypilot.org/compare-versions.html">adds features</a>. The principal difference is that the date version includes editing (via postbacks) and UpdatePanel support, which are not really useful in an ASP.NET MVC application anyway. As with Telerik&#8217;s control, I have to adapt the control for use within ASP.NET MVC. So we selected the open source version, even though the paid version is priced reasonably.</p>
<h3>Adapting DayPilot to ASP.NET MVC</h3>
<p>In order to use the DayPilot control in ASP.NET MVC, I wanted to use markup which would look familiar to ASP.NET MVC developers:</p>
<blockquote>
<pre><code>&lt;%= Html.DayPilot(Model, <strong>new</strong> DayPilotViewOptions
                             {
                                 HourHeight = 30
                             }) %&gt;</code></pre>
</blockquote>
<p>This means that I needed to write an Html helper which will render the control based on the data passed in Model and return the literal HTML markup. In order to make that easier, I created two new types, DayPilotData and DayPilotViewOptions, in order to encapsulate access to the properties of the control. The reason I created two different types was to separate the concerns of data for the events (which will be set up in the controller) and display of the control (which is the concern of the view). The types are trivial, so I&#8217;m not going to show them in this post, but you can examine them in the demo solution. There is an overload to this Html helper which does not include the options argument in case you are happy with the defaults.</p>
<blockquote>
<pre><code><strong>        public static string</strong> DayPilot(
            <strong>this</strong> HtmlHelper helper,
            DayPilotData model,
            DayPilotViewOptions options)
        {
            <strong>var</strong> calendar = <strong>new</strong> DayPilotCalendar();
            <strong>if</strong> (model != null)
            {
                model.CopyTo(calendar);
            }
            <strong>if</strong> (options != null)
            {
                options.CopyTo(calendar);
            }
            <strong>var</strong> sb = <strong>new</strong> System.Text.StringBuilder();
            sb.Append("&lt;div class=\"dayPilot\"&gt;"); // allows working around td cellpadding bug in css
            <strong>using</strong> (<strong>var</strong> sw = <strong>new</strong> System.IO.StringWriter(sb))
            {
                <strong>using</strong> (<strong>var</strong> tw = <strong>new</strong> HtmlTextWriter(sw))
                {
                    calendar.RenderControl(tw);
                }
            }
            sb.Append("&lt;/div&gt;");
            <strong>return</strong> sb.ToString();
        }</code></pre>
</blockquote>
<p>Note the div. The current version of DayPilot astonishingly, as of this writing, does not put a class anywhere in its rendered markup. Since the stylesheet for the default ASP.NET MVC site conflicts with DayPilot, to some degree, I wrapped the whole control in a div so that I could fix the layout in CSS.</p>
<p>Another way which I could have used the control in ASP.NET MVC would be to register a tag prefix and use code behind/code generation, as with standard ASP.NET. I&#8217;ve registered a tag prefix in the demo solution in case you want to try that yourself. Be aware, however, that setting up codebehind and code generation files in an MVC application is somewhat less than simple; doing it right requires, among other things, manual editing of the csproj file. So I do recommend using the control in the way I&#8217;ve illustrated.</p>
<p>Finally, here&#8217;s the source code for the action which supplies data for the control. Since this is a demo solution, I&#8217;m generating random events:</p>
<blockquote>
<pre><code><strong>        public</strong> ActionResult Index()
        {
            <strong>var</strong> r = <strong>new</strong> Random();
            <strong>var</strong> q = <strong>from</strong> i <strong>in</strong> Enumerable.Range(1, 4)
                    <strong>let</strong> start = DateTime.Today.AddHours(r.Next(47))
                    <strong>select new</strong> DayPilotDataItem
                    {
                        Id = i,
                        Start = start,
                        End = start.AddHours(1),
                        Text = string.Format("Event {0}", i)
                    };
            <strong>var</strong> model = <strong>new</strong> DayPilotData
            {
                StartDate = DateTime.Today,
                Days = 2,
                Data = q
            };
            <strong>return</strong> View(model);
        }</code></pre>
</blockquote>
<p>Of course, it&#8217;s just as easy to select data from a database.</p>
<p>The current version of DayPilot has a kind of a weird limitation: You cannot make it smaller, in the vertical dimension, than 30 pixels per hour. Based on some inspection of the source code, I think this is fixable if you are comfortable altering the source. But be aware of the limitation.</p>
<p>There are more DayPilot features which I have not covered, but that should be enough to get you on your way. If you have any questions, post them in comments, and I&#8217;ll see whdat I can do to help out.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38297&amp;akst_action=share-this" onclick="akst_share('38297', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F12%2F38297%2F', 'Using+DayPilot+with+ASP.NET+MVC'); return false;" title="Post to del.icio.us, etc." id="akst_link_38297" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20DayPilot%20with%20ASP.NET%20MVC&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F12%2F38297%2F" id="akst_email_38297" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Understanding LINQ Errors</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/05/05/38274/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/05/05/38274/#comments</comments>
    <pubDate>Tue, 05 May 2009 11:26:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38274</guid>
    <description><![CDATA[If you spend enough time with the PagedList class that I&#8217;ve been using for paging in the method which supplies data to jqGrid, it&#8217;s a near-certainty that sooner or later you will see a LINQ error with Count in the call stack. The error may seem confusing, because it has nothing to do with Count. [...]]]></description>
      <content:encoded><![CDATA[<p>If you spend enough time with the PagedList class that I&#8217;ve been using for paging in <a title="LINQ Extensions" href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">the method which supplies data to jqGrid</a>, it&#8217;s a near-certainty that sooner or later you will see a LINQ error with Count in the call stack. The error may seem confusing, because it has nothing to do with Count. Commentor Graeme has been experimenting with <a href="/files/2009/04/griddemo_1256.zip">my demo solution</a>, and <a href="http://blogs.teamb.com/craigstuntz/2009/04/27/38243/#comment-6168">has run into just this issue</a>:</p>
<blockquote><p>Finding your blogs very helpful - superbly written - just found out about jqgrid last night and have integrated your code into my project.</p>
<p>One thing that didn’t work for me though was the dates fix above…</p>
<p>adding</p>
<p><code>.ToString(System.Globalization.CultureInfo.CurrentUICulture)</code></p>
<p>onto the end of my <code>DateTime </code>values makes everything render Ok but when I try doing a search, it fails. Debugging shows the error is</p>
<p>Method ‘<code>System.String ToString(System.IFormatProvider)</code>’ has no supported translation to SQL.</p>
<p>at the <code>TotalItemCount = source.Count();</code> line of the PagedList.cs file.</p>
<p>Any ideas?</p></blockquote>
<p>In order to understand this error, we need to remember several important things about LINQ:</p>
<ul>
<li>LINQ is lazy. Creating or modifying an IQueryable with methods like <code>Where</code>, <code>Take</code>, <code>OrderBy</code>, etc. does not actually execute the query. The query will only be executed when you call a LINQ method which requires execution to produce its results — like <code>Count</code>.</li>
<li>When a LINQ query expression includes something which looks like a method call, the method is not invoked directly. Instead, what is actually produced is an <a href="http://msdn.microsoft.com/en-us/library/bb397951.aspx"><code>Expression</code></a> representing that method. If the LINQ provider happens to be LINQ to Objects, the method will eventually be invoked when the query is executed. But if it happens to be LINQ to SQL or LINQ to Entities, the method may never be invoked, and instead might be replaced (if possible) with equivalent SQL.</li>
<li>Most LINQ providers do not support every possible LINQ query expression. Most providers don&#8217;t even support the entire LINQ API, and only LINQ to Objects can be presumed to support all method calls on an object in a query. In some cases, <a title="Supported and Unsupported Methods (LINQ to Entities)" href="http://msdn.microsoft.com/en-us/library/bb738550.aspx">as with LINQ to Entities, this is documented</a>. With other providers, you may have to guess/experiment. Any LINQ provider which has to translate a LINQ query expression into SQL syntax can only really support methods which it is hard-coded to recognize. Worse, it is not even uncommon for providers to support one overload of a particular method but not a different overload of the same method. See, for example, the LINQ to Entities document I just linked or the <code>ToString</code> method, which is generally supported in LINQ to Entities/SQL, but has a special overload on the <code>DateTime </code>type which is not supported. Worse still, method calls may be supported in some contexts but not others. Graeme reports that LINQ to SQL accepted the <code>ToString</code> overload in the context of a <code>Select</code>, but not in the context of a <code>Where</code>. This makes sense from an implementation point of view, but means programmers have to be extraordinarily careful about what we include in our LINQ queries, especially when they are constructed dynamically.</li>
</ul>
<p>By now it should be obvious what is going on here: The particular overload of <code>ToString</code> which I used in my example is supported in LINQ to Objects but not in LINQ to SQL in a <code>Where</code> expression. My demo solution used a repository based on LINQ to Objects, so the query I showed worked correctly there. But it does not work with LINQ to SQL. Because LINQ is lazy, you will not actually see an error about this until the query is translated into SQL by the LINQ provider, and that does not happen until the call to <code>Count</code> in <code>PagedList</code>.</p>
<p>This means that when you write a LINQ query expression using LINQ to SQL, LINQ to Entities, etc., you are essentially working in a partially dynamic language. Unless you study the documentation very, very carefully, you will not know for certain until runtime if your query will be accepted by the provider.</p>
<p>So how could we work around this problem?</p>
<ul>
<li>Use a different method or a different overload which is supported by the LINQ provider used in your project. This is fine if an appropriate method/overload exists.</li>
<li>Give up on doing the formatting in C# and use JavaScript instead. This will work, but it&#8217;s a bit like using beheading to cure acne. C# is, after all, a general-purpose programming language. We should not have to give up on formatting a date.</li>
<li>Bring the query into LINQ to Objects using a method such as <code>AsEnumerable</code>. Obviously, we would want to apply the paging and ordering first. In this method, we would execute one query (using LINQ to SQL or something) which would retrieve an ordered list of records for the specified page, using <code>AsEnumerable</code> to transform the results into a List. We would then execute a LINQ to Objects query against this list in order to perform the formatting. This will actually work OK, although it can end up being a good bit of code to write for what should be a fairly simple task.</li>
<li>Write a new LINQ provider which understands the method in question. This seems like an enormous amount of work, but I&#8217;ll include it for completeness.</li>
<li>Separate the concerns of serialization and querying. You can tell by the 50-cent words that this is the solution I prefer. <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>Remember, the original query worked just fine. It is only the serialization to JavaScript which caused unexpected results. One way to fix this is to hide the members which are problematic to serialize and replace them with a string version of same:</p>
<blockquote>
<pre><code><strong>private class</strong> JavaScriptDateFixer
{
    [NonSerialized]
    <strong>internal </strong>DateTime _date;
    <strong>public int</strong> Id { <strong>get; set; </strong>}
    <strong>public int</strong> IntProperty { <strong>get; set; </strong>}
    <strong>public string </strong>StringProperty { <strong>get; set</strong>; }
    <strong>public string </strong>DateProperty { <strong>get </strong>{ <strong>return </strong>_date.ToString(System.Globalization.CultureInfo.CurrentUICulture); } }
}

<strong>public</strong> ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows,<strong> string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>model = <strong>from </strong>entity <strong>in </strong>repository.SelectAll().OrderBy(sidx + " " + sord)
                <strong>select new </strong>JavaScriptDateFixer
                {
                    Id = entity.Id,
                    IntProperty = entity.IntProperty,
                    StringProperty = entity.StringProperty,
                    _date = entity.DateProperty
                };
    <strong>return </strong>Json(model.ToJqGridData(page, rows, <strong>null</strong>, search,
        <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" }));
}
</code></pre>
</blockquote>
<p>Note that even though this code looks quite different, this does almost exactly the same thing as the code I&#8217;ve replaced. The only real difference is that I&#8217;ve delayed the call to ToString until after the query is executed. That&#8217;s enough to keep LINQ to SQL or LINQ to Entities happy.</p>
<p>So with this fix is everything fine? Maybe. I really like LINQ; I think it&#8217;s an extraordinarily powerful tool. But here we have hit upon what I consider to be the single biggest problem with LINQ. The combination of very limited support for all possible query expressions in common LINQ providers like LINQ to SQL and building queries dynamically can be very dangerous. Unless you test all possible query permutations, you cannot be completely confident that any query you build will actually execute successfully. In typical dynamic language programming, you mitigate this problem by writing unit tests. But unit tests are not supposed to connect to a database. Unfortunately, the limitation here is that the point of translation to SQL. So any unit test which mocked the LINQ provider, say, using LINQ to Objects or some other in-memory representation would not actually encounter the limitations we are trying to test.</p>
<p>I have yet to see a really good solution for unit testing LINQ to SQL or LINQ to Entities, one which would combine the desired attributes of not actually connecting to the database while surfacing any potential problems in SQL generation. I suspect that such a beast may never exist for LINQ to SQL, but for LINQ to Entities it seems at least possible. One could write an Entity Framework provider which returns mocked instances of entities. Any LINQ syntax not understood by the Entity Framework would be caught before the mock provider was ever invoked. This is a feature I would like to see in a future version of the Entity Framework.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38274&amp;akst_action=share-this" onclick="akst_share('38274', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F05%2F38274%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Understanding+LINQ+Errors'); return false;" title="Post to del.icio.us, etc." id="akst_link_38274" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Understanding%20LINQ%20Errors&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F05%2F05%2F38274%2F" id="akst_email_38274" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery Index Inconsistency</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/30/38271/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/30/38271/#comments</comments>
    <pubDate>Thu, 30 Apr 2009 12:15:02 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38271</guid>
    <description><![CDATA[The jQuery :nth-child selector has an "index" argument which is 1-based. But the jQuery "index" method, which is arguably the converse of the selector, returns a 0-based result. This is very easy to work around once you&#8217;re aware of it, but it&#8217;s surprising in a library which is, generally, designed both well and consistently.
Share This [...]]]></description>
      <content:encoded><![CDATA[<p>The jQuery <a title="      * Main Page     * Downloading jQuery     * How jQuery Works     * FAQ     * Tutorials     * Using jQuery with Other Libraries     * Variable Types  API Reference      * jQuery Core     * Selectors     * Attributes     * Traversing     * Manipulation     * CSS     * Events     * Effects     * Ajax     * Utilities     * jQuery UI  Plugins      * Plugin Repository     * Authoring  Support      * Mailing List and Chat     * Submit New Bug  About jQuery      * Contributors     * History of jQuery     * Sites Using jQuery     * Browser Compatibility     * Licensing     * Donate  Toolbox      * What links here     * Related changes     * Upload file     * Special pages     * Printable version     * Permanent link  Views      * Article     * Discussion     * Edit     * History  Personal tools      * Log in / create account  Selectors/nthChild" href="http://docs.jquery.com/Selectors/nthChild#index">:nth-child selector has an "index" argument which is 1-based</a>. But the jQuery "index" method, which is arguably the converse of the selector, <a title=" Core/index" href="http://docs.jquery.com/Core/index#subject">returns a 0-based result</a>. This is very easy to work around once you&#8217;re aware of it, but it&#8217;s surprising in a library which is, generally, designed both well and consistently.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38271&amp;akst_action=share-this" onclick="akst_share('38271', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F30%2F38271%2F', 'jQuery+Index+Inconsistency'); return false;" title="Post to del.icio.us, etc." id="akst_link_38271" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%20Index%20Inconsistency&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F30%2F38271%2F" id="akst_email_38271" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Deleting Records</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/29/38266/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/29/38266/#comments</comments>
    <pubDate>Wed, 29 Apr 2009 15:46:48 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38266</guid>
    <description><![CDATA[This is the fifth post in a series on using jqGrid with ASP.NET MVC. Today, we’re going to begin examining the grid&#8217;s editing features by implementing deletes. If you’re new to the series, you might want to start at the beginning.
The delete feature of jqGrid is, oddly, almost entirely undocumented, even though there quite a [...]]]></description>
      <content:encoded><![CDATA[<p>This is the fifth post in a series on using jqGrid with ASP.NET MVC. Today, we’re going to begin examining the grid&#8217;s editing features by implementing deletes. If you’re new to the series, you might want to start at <a title="Introduction" href="/craigstuntz/2009/04/14/38200/">the beginning</a>.</p>
<p>The delete feature of jqGrid is, oddly, almost entirely undocumented, even though there quite a few examples of different methods of <a href="http://www.secondpersonplural.ca/jqgriddocs/index.htm">editing</a>, and inserts are documented, to a lesser extent. But it does exist; I just had to read the source code to figure out how it works.</p>
<p>JqGrid has three different methods of editing data. The cell edit feature allows the user to edit a single cell the grid at a time, and saves the data when the cell loses focus. The row edit feature works similarly, but does not save the data until the row loses focus. The form edit feature shows a modal dialog instead of editing the values inline. Of these three, the form edit feature is the only one which supports deletes. However, you can still use one of the other "modes" for editing, if you like. Just be aware that when you do a delete, you will be in the form edit code. Also, deletes won&#8217;t work if you change the grid&#8217;s configuration to disable the form edit feature.</p>
<p>In order to allow the user to delete a row, I need to:</p>
<ul>
<li>Add a delete button to the grid&#8217;s toolbar. I could, of course, use a custom button or something instead of the grid&#8217;s toolbar if I chose to do so.</li>
<li>Specify a URL for the delete action</li>
<li>Implement a delete action on the controller</li>
</ul>
<p>I can accomplish the first two tasks by making a slight change to the JavaScript that configures the grid:</p>
<blockquote><p><code>}).<a href="http://www.secondpersonplural.ca/jqgriddocs/_2er0j2mvk.htm">navGrid</a>(pager, { edit: false, add: false, del: <strong>true</strong>, search: false }<strong>, {}, {}, {url: "Delete"}</strong>);</code></p></blockquote>
<p>I&#8217;ve highlighted the parts I&#8217;ve changed in boldface. Changing the "<code>del</code>" property to true turns on the toolbutton. The fifth argument is an object specifying options for the delete action, of which I have only specified the URL. This is important: The only places you can specify the URL for delete are in the arguments to the <code>delGridRow</code> method or in the toolbar&#8217;s configuration. There is not a "delete URL" property of the grid itself.</p>
<p>If you don&#8217;t specify a delete URL in this way, the grid will presume that you want to send delete requests to the URL you have specified for editing rows. There will be an "<code>oper</code>” value in the submitted form indicating that the request is a delete rather than an edit. But I prefer to use a separate URL for delete, because I think that fits more naturally in the ASP.NET MVC paradigm.</p>
<p>Now let&#8217;s write an action to handle the delete:</p>
<blockquote>
<pre><code>[AcceptVerbs(HttpVerbs.Post)]
<strong>public </strong>ActionResult Delete(<strong>int </strong>id)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>deleted = repository.Delete(id);
    <strong>if </strong>(!deleted)
    {
        Response.StatusCode = 500;
        <strong>return </strong>Content("Record not found.");
    }
    <strong>return </strong>Json(true);
}</code></pre>
</blockquote>
<p>Again, I&#8217;ll note that I&#8217;m using a mock repository for this demo so that you can compile and run the solution without needing to set up a database. Since the mock repository is based on IList, the Delete method of the repository returns a Boolean indicating whether or not the requested record was found, since that is how IList behaves. It would probably be more correct to return a partial view in the event of an error rather than specifying the contents directly, but error handling is a subject I hope to cover in more depth later on. For the time being, simply changing the StatusCode will tell the grid when something does not work.</p>
<p>If the delete was successful, I return "true." By default, the grid ignores returned data when the operation is successful. However, you can handle the grid&#8217;s afterSubmit event, which will be passed any data you do return. So what you choose to return, and what you do with it, is entirely up to you.</p>
<p>With all that in place, deletes work as expected. I&#8217;m not going to update the demo solution just yet, because I&#8217;ll be covering edits and inserts <a href="http://catb.org/jargon/html/R/Real-Soon-Now.html">real soon now</a>. But first I need to <a title="Understanding LINQ Errors" href="http://blogs.teamb.com/craigstuntz/2009/05/05/38274/">revisit formatting and explain more about LINQ</a>".</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38266&amp;akst_action=share-this" onclick="akst_share('38266', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F29%2F38266%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Deleting+Records'); return false;" title="Post to del.icio.us, etc." id="akst_link_38266" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Deleting%20Records&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F29%2F38266%2F" id="akst_email_38266" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Search and Formatting</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/27/38243/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/27/38243/#comments</comments>
    <pubDate>Mon, 27 Apr 2009 12:44:54 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38243</guid>
    <description><![CDATA[This is the fourth post in a series on using jqGrid with ASP.NET MVC. Today, we&#8217;re going to examine search and formatting results. I will implement a search feature and fix the problem with formatting date columns which I observed in the last post. I&#8217;ve updated the demo solution with these new features, and also [...]]]></description>
      <content:encoded><![CDATA[<p>This is the fourth post in a series on using jqGrid with ASP.NET MVC. Today, we&#8217;re going to examine search and formatting results. I will implement a search feature and fix the problem with formatting date columns which I observed in <a title="Finally, A Solution" href="http://blogs.teamb.com/craigstuntz/2009/04/17/38229/">the last post</a>. I&#8217;ve updated the <strong><a href="/files/2009/04/griddemo_1256.zip">demo solution</a></strong> with these new features, and also fixed <a href="http://blogs.teamb.com/craigstuntz/2009/04/17/38229/#comment-5754">a bug reported by <span class="comment-author vcard"><span class="fn n">Andrey</span></span></a> last time. If you&#8217;re new to the series, you might want to start at <a title="Introduction" href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">the beginning</a>.</p>
<p>First, let&#8217;s fix the date display. The reason the <a href="http://blogs.teamb.com/files/2009/04/jqgriddemoapp1_1192.png">date appeared so oddly</a> is that there is no official support for Date types in JSON, even though JavaScript has a date type. Microsoft, therefore, invented their own way of encoding dates for their JSON serializer, which jqGrid does not understand. There are two possible ways to fix the problem. The first is to keep sending the data to the grid in the Microsoft format, and write a <a href="http://www.secondpersonplural.ca/jqgriddocs/_2kn0mlo1p.htm">custom formatter for the grid</a> to parse that into a human-readable string. The second is to change the data we send to the grid. Both ways work, but I&#8217;m going to demonstrate the second method, mostly because I find C#&#8217;s date handling features superior to (<a title="date basics" href="http://blog.boyet.com/blog/javascriptlessons/javascript-for-c-developers-date-basics/">and less confusing than</a>) JavaScript&#8217;s.</p>
<p>In order to change the date "column" in the results of the query to a formatted string, we simply need to project into an anonymous type. However, this would break the sort, because a text sort on a formatted date will not be in the correct order. Hence, it is necessary to apply the sort before projecting. So I add an OrderBy to the query, and pass null as the <code>orderBy</code> argument to the <code>ToJqGridData</code> method.</p>
<blockquote>
<pre><code><strong>public </strong>ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>repository = <strong>new </strong>Repository();
    <strong>var </strong>model = <strong>from </strong>entity <strong>in </strong>repository.SelectAll().OrderBy(sidx + " " + sord)
                <strong>select new</strong>
                {
                    Id = entity.Id,
                    IntProperty = entity.IntProperty,
                    StringProperty = entity.StringProperty,
                    DateProperty = entity.DateProperty.ToString(
                        System.Globalization.CultureInfo.CurrentUICulture)
                };
    <strong>return </strong>Json(model.ToJqGridData(page, rows, <strong>null</strong>, search,
        <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" }));
}</code></pre>
</blockquote>
<p>Note that in this revised solution I&#8217;ve updated the mock repository to return more sensible dates.</p>
<p><strong>Important update:</strong> This code works correctly with LINQ to Objects, as with my demo repository, but will not work with LINQ to SQL. <a title="Understanding LINQ Errors" href="http://blogs.teamb.com/craigstuntz/2009/05/05/38274/">I have addressed this issue in a subsequent post</a>.</p>
<p>Now let&#8217;s add a search feature. One of the problems in making a "demo" search is that search is a highly application-specific feature, both in terms of implementation and in terms of user experience. JqGrid&#8217;s search feature presumes that you want a search which looks something like this:</p>
<p><a href="/files/2009/04/jqgridsearchform_1250.png"><img src="/files/2009/04/jqgridsearchform_1250.png" alt="" width="411" height="61" /></a></p>
<p>Visually, there are lots of variations on this theme available, but in terms of the use case they all presume that the user will specify which fields she would like to search. However, I prefer a "Google-style" interface with just a search box and an implementation that can (hopefully) figure out what the user actually wants. So that&#8217;s what I&#8217;m going to demonstrate. The needs of your application may be different. The important thing to take away from this demonstration is that the jqGrid search feature can be co-opted to fit <em>your </em>design.</p>
<p>I want the search box to appear above the grid at all times, rather than requiring the user to press a toolbutton to see it. So first I need to add an empty div to the markup in order to indicate where the search box will be positioned, relative to the grid:</p>
<blockquote>
<pre><code>    &lt;h2&gt;GridDemo&lt;/h2&gt;
    &lt;div id="search"&gt;&lt;/div&gt;
    &lt;table id="grid" class="scroll" cellpadding="0" cellspacing="0"&gt;&lt;/table&gt;
    &lt;div id="pager" class="scroll" style="text-align:center;"&gt;&lt;/div&gt;</code></pre>
</blockquote>
<p>Next, I add a small bit of JavaScript to tell jqGrid to replace this div with a search control:</p>
<blockquote><p><code> </code></p>
<pre>    search.filterGrid("#" + grid.attr("id"), {
        gridModel: false,
        filterModel: [{
            label: 'Search',
            name: 'search',
            stype: 'text'
        }]
    });</pre>
</blockquote>
<p>The <code>filterModel </code>tells the grid to show a search control for one column, called "Search." Note that the entities I&#8217;m returning do not have a property called "search." That&#8217;s OK. When the user types something in the search box and presses enter, the grid will add a query string parameter to its request for the data of the form "<code>search=WhatTheUserTyped</code>". That&#8217;s what I want, and the fact that there is no "search" column in the data does not adversely affect the grid in any way.</p>
<p>The first argument to <code>filterGrid </code>is a little odd. I&#8217;m required to pass a jQuery selector as a string rather than being able to pass a jQuery object directly. Since this is all inside a method which accepts jQuery objects as arguments (rather than hard-coding the IDs of the DOM objects in the method, for unit-testability), I have to "decode" the jQuery object into a selector string. But note that I did not need to do that when setting up the pager or the grid itself. Like I said before, the grid&#8217;s API is consistently inconsistent.</p>
<p>As you can see in the code at the beginning of this post, the GridDemoData action just passes the search query string parameter through to the ToJqGridData method unchanged. Inside that method, I use Dynamic LINQ to alter the IQueryable to implement the search. I&#8217;ve cleaned up this method substantially since I first posted the code. Here&#8217;s the revised method:</p>
<blockquote><p><code> </code></p>
<pre><em>/// &lt;summary&gt;
/// Adds a Where to a Queryable list of entity instances.  In other words, filter the list
/// based on the search parameters passed.
/// &lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Entity type contained within the list&lt;/typeparam&gt;
/// &lt;param name="baseList"&gt;Unfiltered list&lt;/param&gt;
/// &lt;param name="searchQuery"&gt;Whatever the user typed into the search box&lt;/param&gt;
/// &lt;param name="searchColumns"&gt;List of entity properties which should be included in the
/// search.  If any property in an entity instance begins with the search query, it will
/// be included in the result.&lt;/param&gt;
/// &lt;returns&gt;Filtered list.  Note that the query will not actually be executed until the
/// IQueryable is enumerated.&lt;/returns&gt;</em>
<strong>private static </strong>IQueryable&lt;T&gt; ListAddSearchQuery&lt;T&gt;(
    IQueryable&lt;T&gt; baseList,
    <strong>string </strong>searchQuery,
    IEnumerable&lt;<strong>string</strong>&gt; searchColumns)
{
    <strong>if </strong>((String.IsNullOrEmpty(searchQuery)) | (searchColumns == null)) <strong>return </strong>baseList;
    <strong>const string</strong> strpredicateFormat = "{0}.ToString().StartsWith(@0)";
    <strong>var </strong>searchExpression = <strong>new </strong>System.Text.StringBuilder();
    <strong>string </strong>orPart = String.Empty;
    <strong>foreach </strong>(<strong>string </strong>column <strong>in </strong>searchColumns)
    {
        searchExpression.Append(orPart);
        searchExpression.AppendFormat(strpredicateFormat, column, searchQuery);
        orPart = " OR ";
    }
    <strong>var </strong>filteredList = baseList.Where(searchExpression.ToString(), searchQuery);
    <strong>return </strong>filteredList;
}</pre>
</blockquote>
<p>Importantly, this method is simply adding to the expression represented by the IQueryable. It does not actually implement the search. So any search methodology which understands LINQ can deal with its results. At least, theoretically. In practice, LINQ providers vary greatly in terms of which LINQ features they support. So although this method works fine with LINQ to Objects (as used in the rest of the demo solution) I cannot guarantee that it will work with every LINQ provider in the world. You have to try, and revise it to fit the capabilities of the provider you&#8217;re using.</p>
<p>Putting all these pieces together, I now have a search feature which does what I want:</p>
<p><a href="/files/2009/04/jqgridwithsearch_1253.png"><img src="/files/2009/04/jqgridwithsearch_1253.png" alt="" width="457" height="132" /></a><br />
Be sure to <strong><a href="/files/2009/04/griddemo_1256.zip">download the updated solution</a></strong> in order to get the bug fixes and new features.</p>
<p>As a special, no-extra-charge bonus, the updated solution also includes a demonstration of using the grid&#8217;s tree view mode with client-side data from a JavaScript function. This has nothing to do with ASP.NET MVC; it&#8217;s just an example of how to use a grid feature which I wrote in response to <a href="http://www.trirand.com/blog/?page_id=18/treegrid/empty-treegrid-with-client-side-data/page-1/post-6175/#p6175">a request in the jqGrid support forums</a>.</p>
<p>That&#8217;s all for today. <a title="Deletes" href="http://blogs.teamb.com/craigstuntz/2009/04/29/38266/">In the next post in the series, I&#8217;ll begin to demonstrate the grid&#8217;s editing features</a>, and how to use them in an ASP.NET MVC application. But I will also take requests. If there&#8217;s a grid feature you&#8217;d like to see demonstrated query question regarding using the grid in ASP.NET MVC, please feel free to make a request in comments, and I will answer it as best I can.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38243&amp;akst_action=share-this" onclick="akst_share('38243', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F27%2F38243%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Search+and+Formatting'); return false;" title="Post to del.icio.us, etc." id="akst_link_38243" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Search%20and%20Formatting&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F27%2F38243%2F" id="akst_email_38243" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Crash Course In Failure</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/23/38241/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/23/38241/#comments</comments>
    <pubDate>Thu, 23 Apr 2009 10:37:39 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38241</guid>
    <description><![CDATA[My new article, A Crash Course In Failure, has just been published on the architecture site NPlus1. In it, I examine the surprisingly persuasive argument that unplugging entire racks of live, production servers is not only a good idea, but that shutting them down any other way is a mistake, and what this means for [...]]]></description>
      <content:encoded><![CDATA[<p>My new article, <a href="http://nplus1.org/articles/a-crash-course-in-failure/">A Crash Course In Failure</a>, has just been published on the architecture site NPlus1. In it, I examine the surprisingly persuasive argument that unplugging entire racks of live, production servers is not only a good idea, but that shutting them down any other way is a mistake, and what this means for how we design software.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38241&amp;akst_action=share-this" onclick="akst_share('38241', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F23%2F38241%2F', 'A+Crash+Course+In+Failure'); return false;" title="Post to del.icio.us, etc." id="akst_link_38241" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Crash%20Course%20In%20Failure&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F23%2F38241%2F" id="akst_email_38241" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero Jobs and jqGrid Trees</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/20/38238/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/20/38238/#comments</comments>
    <pubDate>Mon, 20 Apr 2009 12:37:14 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38238</guid>
    <description><![CDATA[I have a couple of short updates on topics I&#8217;ve covered recently.
On The Podcast at Delphi.org, Nick Hodges confirms my earlier speculation about reorganization in the "CodeGear" group at Embarcadero. The whole show is worth listening to. Congratulations are due to Chris Pattinson, who was promoted to Director of Quality for all of Embarcadero. Time [...]]]></description>
      <content:encoded><![CDATA[<p>I have a couple of short updates on topics I&#8217;ve covered recently.</p>
<p>On The Podcast at Delphi.org, <a title="27 - Nick Hodges - R&amp;D Manager" href="http://www.delphi.org/2009/04/27-nick-hodges-rd-manager/">Nick Hodges confirms</a> my earlier <a title="Embarcadero Development Tools Reorganization?" href="http://blogs.teamb.com/craigstuntz/2009/04/16/38223/">speculation about reorganization in the "CodeGear" group at Embarcadero</a>. The whole show is worth listening to. Congratulations are due to <a href="http://blogs.embarcadero.com/chrispattinson/">Chris Pattinson</a>, who was promoted to Director of Quality for all of Embarcadero. Time to update the subtitle of your blog, Chris! (And maybe even write a post or two&#8230;) Sounds like good changes all around. You read it here first, folks!</p>
<p>I wrote <a href="http://www.trirand.com/blog/?page_id=18/treegrid/empty-treegrid-with-client-side-data/page-1/post-6175/#p6175">a short demo showing how to use jqGrid in tree grid node with client-side data</a> supplied by a JavaScript function.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38238&amp;akst_action=share-this" onclick="akst_share('38238', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F20%2F38238%2F', 'Embarcadero+Jobs+and+jqGrid+Trees'); return false;" title="Post to del.icio.us, etc." id="akst_link_38238" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero%20Jobs%20and%20jqGrid%20Trees&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F20%2F38238%2F" id="akst_email_38238" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Finally, A Solution</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/17/38229/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/17/38229/#comments</comments>
    <pubDate>Fri, 17 Apr 2009 14:07:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38229</guid>
    <description><![CDATA[Having introduced jqGrid and written LINQ extension methods to make supplying data to the grid easy, we&#8217;re now ready to put together a demo application. The solution I&#8217;m going to build demonstrates sorting and paging. In a future post, I will enhance it to demonstrate search, formatting, and editing data. I&#8217;ve made the demo application [...]]]></description>
      <content:encoded><![CDATA[<p>Having <a href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">introduced jqGrid</a> and written <a href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">LINQ extension methods</a> to make supplying data to the grid easy, we&#8217;re now ready to put together a demo application. The solution I&#8217;m going to build demonstrates sorting and paging. In a future post, I will enhance it to demonstrate search, formatting, and editing data. I&#8217;ve made the demo application available for download, but be advised that I intend to update it in the next few days; it&#8217;s currently a work in progress.</p>
<p>Rather than make you set up the Northwind database, I&#8217;ve written a quick, mock repository which supplies random data for the application. But the data persists for the lifetime of the app, so I&#8217;ll be able to demonstrate sorting, paging, etc. This way you can just run the application, without having to set up SQL Server.</p>
<p>So let&#8217;s write some code display a grid.</p>
<p>The data I&#8217;m going to display in the grid is a fairly useless type:</p>
<blockquote>
<pre><code>    <strong>public class </strong>SomeEntity
    {
        <strong>public int </strong>Id { <strong>get; set; </strong>}
        <strong>public int </strong>IntProperty { <strong>get; set; </strong>}
        <strong>public string </strong>StringProperty { <strong>get; set</strong>; }
        <strong>public </strong>DateTime DateProperty { <strong>get; set; </strong>}
    }</code></pre>
</blockquote>
<p>We need two actions. The first will display the page containing the grid. The second supplies data for one page of the grid. Remember, the grid can page through large datasets. It will only request one page of data at a time.</p>
<pre><code>        <strong>public </strong>ActionResult GridDemo()
        {
            <strong>return </strong>View();
        }

        <strong>public </strong>ActionResult GridDemoData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
        {
            <strong>var </strong>repository = <strong>new </strong>Repository();
            <strong>var </strong>model = repository.SelectAll().ToJqGridData(page, rows, sidx + " " + sord, search,
                <strong>new</strong>[] { "IntProperty", "StringProperty", "DateProperty" });
            <strong>return </strong>Json(model);
        }</code></pre>
<p>The first action simply returns a view containing the HTML table which will eventually become the grid. It doesn&#8217;t need a model, because the grid will request its data asynchronously. The second action handles the data requested by the grid.</p>
<p>In order to make this work, we need HTML elements for the grid and its pager in the view, along with a reference to the JavaScript which will turn those elements into the grid.</p>
<blockquote>
<pre><code>&lt;asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"&gt;
    &lt;h2&gt;GridDemo&lt;/h2&gt;
    &lt;table id="grid" class="scroll" cellpadding="0" cellspacing="0"&gt;&lt;/table&gt;
    &lt;div id="pager" class="scroll" style="text-align:center;"&gt;&lt;/div&gt;
&lt;/asp:Content&gt;

&lt;asp:Content ID="Script" ContentPlaceHolderID="ScriptContent" runat="server"&gt;
    &lt;script language="javascript" type="text/javascript" src="&lt;%= Url.Content("~/Scripts/Home.GridDemo.js") %&gt;"&gt;&lt;/script&gt;
&lt;/asp:Content&gt;</code></pre>
</blockquote>
<p>The JavaScript file is where the grid itself is configured.</p>
<blockquote>
<pre><code>$(document).ready(<strong>function</strong>() {
    GridDemo.Home.GridDemo.setupGrid($("#grid"), $("#pager"));
});

GridDemo.Home.GridDemo = {
    setupGrid: <strong>function</strong>(grid, pager) {
        grid.jqGrid({
            colNames: ['Int', 'String', 'Date'],
            colModel: [
                        { name: 'IntProperty', index: 'IntProperty' },
                        { name: 'StringProperty', index: 'StringProperty' },
                        { name: 'DateProperty', index: 'DateProperty' },
                      ],
            pager: pager,
            sortname: 'IntProperty',
            rowNum: 10,
            rowList: [10, 20, 50],
            sortorder: "asc",
            url: "GridDemoData"
        }).navGrid(pager, { edit: <strong>false</strong>, add: <strong>false</strong>, del: <strong>false</strong>, search: <strong>false </strong>});
    }
};</code></pre>
</blockquote>
<p>Important to note here are:</p>
<ul>
<li><code>colNames</code>, the grid column captions the user sees.</li>
<li><code>colModel</code>,which includes the property <code>name</code>, which is the field name in the returned JSON data which supplies the data for that column, and <code>index</code>, which is the name which will be sent to the <code>GridDemoData </code>action as the <code>sidx </code>(field name to sort on) argument when you click on a grid header. There are a number of other properties you can set here which control editing, with, formatting, etc. See <a href="http://www.secondpersonplural.ca/jqgriddocs/_2eb0fihps.htm">the documentation</a> for full details. Importantly, <code>colNames </code>and <code>colModel </code>must have the same number of entries, and be in the same order.</li>
<li><code>url</code>, which tells the grid where to get its data. You&#8217;ll notice that the value I&#8217;ve passed is the name of the second action.</li>
</ul>
<p>As I mentioned in <a title="LINQ Extensions" href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">the last post</a>, I set a number of the grid options in a script referenced by the Site.Master, in order to prevent having to set them on every grid I create. The configuration idea for the grid on an individual page should be only the things that are unique to that page. So there is a fair bit of configuration for the grid which is not included here. In addition, the Site.Master contains references to the grid&#8217;s JavaScript and CSS files.</p>
<p>Finally, it&#8217;s worth mentioning that when you add jqGrid to a project you need to edit the jQuery.jqGrid.js file to tell the grid where to find the rest of the JS files it needs. Once you look at this file, it is obvious what you need to change.</p>
<p>At this point, I&#8217;m going to make the demo application available for download, so that you can experiment with it yourself. However, I&#8217;ll caution that I intend to update it when I write the next post in this series. In other words, the current download is a work in progress. It will change in the next few days.</p>
<p><a href="/files/2009/04/griddemo_1256.zip">Download the Solution (587 KB)</a></p>
<p>So let&#8217;s run the solution and see what we get:</p>
<p><a href="/files/2009/04/jqgriddemoapp1_1192.png"><img src="/files/2009/04/jqgriddemoapp1_1192.png" alt="jqGrid demo app version 1" width="500" height="464" /></a><br />
OK, the hideous and eyestrain-inducing clash between the default MVC theme and the jQuery UI "lightness" theme included with the grid download notwithstanding, this is actually not bad. Sorting and paging both work, and performance is very good.</p>
<p>But what&#8217;s the deal with the data in that date column? It turns out that there is no standard representation of a date in JSON, so Microsoft invented their own. The grid doesn&#8217;t know about this special format. <a title="Search and Formatting" href="http://blogs.teamb.com/craigstuntz/2009/04/27/38243/">We&#8217;ll clean that up in the next post in this series and also cover search. </a>Stay tuned!</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38229&amp;akst_action=share-this" onclick="akst_share('38229', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F17%2F38229%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Finally%2C+A+Solution'); return false;" title="Post to del.icio.us, etc." id="akst_link_38229" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Finally%2C%20A%20Solution&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F17%2F38229%2F" id="akst_email_38229" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Embarcadero Development Tools Reorganization?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/16/38223/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/16/38223/#comments</comments>
    <pubDate>Thu, 16 Apr 2009 10:44:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38223</guid>
    <description><![CDATA[Item 1:
Nick Hodges has a new role/job title.
Item 2:
During his presentation to the Columbus Architecture Group a couple of weeks ago, Mike Rozlog handed out business cards which gave his title as "Senior Project Manager, Java Tools." He told us that in a couple of days he would have new business cards, because his role [...]]]></description>
      <content:encoded><![CDATA[<h5>Item 1:</h5>
<p><a href="http://blogs.embarcadero.com/nickhodges/2009/04/14/39230">Nick Hodges has a new role/job title.</a></p>
<h5>Item 2:</h5>
<p>During <a href="http://blogs.teamb.com/craigstuntz/2009/04/06/38188/">his presentation to the Columbus Architecture Group</a> a couple of weeks ago, Mike Rozlog handed out business cards which gave his title as "Senior Project Manager, Java Tools." He told us that in a couple of days he would have new business cards, because his role was changing. He didn&#8217;t tell us precisely what the new role would be, but I got the feeling that, like Nick, he was happy with the change.</p>
<p>Now, it is of course possible that these two changes happening so close together is merely a coincidence. But my <em><strong>personal speculation</strong></em> is that there are bigger plans afoot, and I&#8217;m glad to see that Mike and Nick, two people I trust, seem to be happy with them.</p>
<p>Repeat: <em>This is just my personal speculation</em>. It is based on the evidence above, not inside information. I could be wrong.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38223&amp;akst_action=share-this" onclick="akst_share('38223', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F16%2F38223%2F', 'Embarcadero+Development+Tools+Reorganization%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38223" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Embarcadero%20Development%20Tools%20Reorganization%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F16%2F38223%2F" id="akst_email_38223" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: LINQ Extensions</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/15/38212/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/15/38212/#comments</comments>
    <pubDate>Wed, 15 Apr 2009 11:25:36 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38212</guid>
    <description><![CDATA[Mere hours after I posted the first in a planned series of posts on using jqGrid in ASP.NET MVC applications, Phil Haack, a rather-more-widely-read-ASP.NET-MVC-blogger, wrote a long post on, er, exactly the same thing. Who, me, bitter? Naahhh…  
But it turns out that we&#8217;re using the grid in a different way, and I think [...]]]></description>
      <content:encoded><![CDATA[<p>Mere hours after I posted <a title="Introduction" href="http://blogs.teamb.com/craigstuntz/2009/04/14/38200/">the first in a planned series of posts on using jqGrid in ASP.NET MVC applications</a>, Phil Haack, a rather-more-widely-read-ASP.NET-MVC-blogger, wrote <a title="Using jQuery Grid With ASP.NET MVC" href="http://haacked.com/archive/2009/04/14/using-jquery-grid-with-asp.net-mvc.aspx">a long post on, er, exactly the same thing</a>. Who, me, bitter? Naahhh… <img src='http://blogs.teamb.com/feeds/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>But it turns out that we&#8217;re using the grid in a different way, and I think the difference is important. So rather than just referring you to Phil&#8217;s post and skipping the rest of the series, I think I still have some important information to contribute. In particular, I&#8217;m using the grid in a way which allows me to write an extension method for <code>IQueryable&lt;T&gt;</code> which returns data suitable for the grid, without having to know anything about the type <code>T</code>. If you look closely at the code in Phil&#8217;s post, you will see that populating the cell array requires custom code (or use of reflection) every time you want to return data to a grid.</p>
<p>It&#8217;s important to me that the method should work without knowing anything about the type of the data in the list because I don&#8217;t want to have to write repetitious code in every action method which supplies data to a grid to shape the data according to the grid&#8217;s needs, and because I generally use anonymous types for JSON serialization. JSON cannot handle object graphs with cycles (i.e., a "circle" of objects which all reference each other). The .NET JSON serializer will throw an exception if you pass it an object which contains a circular reference, or refers to another object which does. Since this is largely data-dependent and, worse, can be occasionally masked by lazy loading and the like, the safest way to serialize to JSON is to pass it data which provably can never contain a cycle. Anonymous types work really well for this. I&#8217;ll probably elaborate on this point in a future post. For the time being, the important thing is that I need to be able to take any IQueryable and turn it into data suitable for the grid, without having to think about what type that list might contain.</p>
<p><strong>In a nutshell, this is what I want to be able to do:</strong></p>
<blockquote>
<pre><code><strong>public </strong>JsonResult ListGridData(<strong>int </strong>page, <strong>int </strong>rows, <strong>string </strong>search, <strong>string </strong>sidx, <strong>string </strong>sord)
{
    <strong>var </strong>model = repository.SelectAll().ToJqGridData(page, rows, sidx + " " + sord, search,
      <strong>new</strong>[] { "Column1", "</code><code>Column2</code><code>", "</code><code>Column3</code><code>" })
    <strong>return </strong>Json(model);
}</code></pre>
</blockquote>
<p>In this example, <code>repository.SelectAll()</code> returns an <code>IQueryable&lt;TSomething&gt;</code>. I&#8217;ve written a method, <code>ToJqGridData</code>, which can transform that <code>IQueryable</code> into data suitable for the grid without having to know what <code>TSomething</code> is. (What the heck is that string array? Don&#8217;t worry about that just yet; I&#8217;ll cover it in a little bit.) The argument names aren&#8217;t what I would have picked, but they come from the grid. There is probably a way to change them, but I&#8217;ve never bothered to look.</p>
<p>The key to this is a grid property called <code>jsonReader.repeatitems</code>. I&#8217;m not sure why it&#8217;s called <code>repeatitems</code>, but here&#8217;s what it does. When <code>repeatitems </code>is true (the default), data is returned to the grid in a "cell array," like in Phil&#8217;s post. That is, an individual row of data in the JSON looks like this:</p>
<blockquote>
<pre>{id:<span class="codestring">"1"</span>, cell:[<span class="codestring">"cell11"</span>, <span class="codestring">"cell12"</span>, <span class="codestring">"cell13"</span>]}</pre>
</blockquote>
<p>When <code>repeatitems </code>is false, the data looks like a regular object in JSON format:</p>
<blockquote>
<pre>{id:<span class="codestring">"45678"</span>,name:<span class="codestring">"Speakers"</span>,note:<span class="codestring">"note"</span>,stock:<span class="codestring">"false"</span>,ship:<span class="codestring">"4"</span>}</pre>
</blockquote>
<p>Interestingly, it turns out that <em>this is the format the .NET JSON serializer already uses</em>. So I don&#8217;t have to write <em>any </em>code to get this portion of the data into the right shape. I just hand an object to the JSON serializer and let it do its thing. The only things I need to do to make the data work for the grid is to handle paging, sorting, search, and provide certain other bits of data, like the number of rows.</p>
<p>But, as you may have noticed, I&#8217;m lazy. Why write code when someone else has already done it? <a title="PagedList&lt;T&gt;" href="http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/">Rob Conery wrote a decent type for paging eons ago</a>, and <a title="PagedList Strikes Back" href="http://www.squaredroot.com/post/2008/07/08/PagedList-Strikes-Back.aspx">Troy Goode enhanced it</a>. So I&#8217;m going to use their work instead of re-writing paging. It turns out this type already computes most of what the grid needs to know. And Microsoft has this thing called Dynamic LINQ which can deal with ordering and filtering by property names, mostly. All I have to do is tie this stuff together.</p>
<p>I wrote a type to hold the data which the grid needs. You can actually use an anonymous type for this; the JavaScript grid obviously doesn&#8217;t care if the data it receives comes from an anonymous type or not, but because I am writing extension methods to IQueryable, it was convenient for me to have a non-anonymous type so that the extension methods could build on each other. This type represents one page of data requested by the grid:</p>
<blockquote>
<pre><code><strong>namespace </strong>GridDemo.Models
{
<em>    /// &lt;summary&gt;
    /// This type is designed to conform to the structure required by the JqGrid JavaScript component.
    /// It has all of the properties required by the grid. When this type is serialized to JSON, the resulting
    /// JSON will be in the structure expected by the grid when it fetches pages of data via AJAX calls.
    /// &lt;/summary&gt;</em>
    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
        Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Jq",
        Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
    <strong>public class</strong> JqGridData
    {
<em>        /// &lt;summary&gt;
        /// The number of pages which should be displayed in the paging controls at the bottom of the grid.
        /// &lt;/summary&gt;</em>
        <strong>public int </strong>Total {<strong> get; set;</strong> }
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The current page number which should be highlighted in the paging controls at the bottom of the grid.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public int </strong>Page { <strong>get; set;</strong> }
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The total number of records in the entire data set, not just the portion returned in Rows.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public int </strong>Records { <strong>get; set; </strong>}</code><code>
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// The data that will actually be displayed in the grid.
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public </strong>IEnumerable Rows { <strong>get; set; </strong>}
</code><em><code>        /// &lt;summary&gt;
</code><code>        /// Arbitrary data to be returned to the grid along with the row data. Leave null if not using. Must be serializable to JSON!
</code></em><code><em>        /// &lt;/summary&gt;</em>
</code><code>        <strong>public object </strong>UserData { <strong>get; set; </strong>}</code><code>
</code><code>    }
}</code></pre>
</blockquote>
<p>Note that I&#8217;ve used C# capitalization for the property names. This is not what the grid expects. But I have to tell the grid that I&#8217;m using a non-default value for <code>repeatitems </code>anyway, so it&#8217;s nice to follow C# conventions.</p>
<p>We have lots of grids in our application, so rather than configuring each grid individually, we set defaults for the grid in one place. In a JavaScript file referenced by the Site.Master, this method is called in the jQuery ready event:</p>
<blockquote>
<pre><code>    setDefaults: <strong>function</strong>() {
        $.jgrid.defaults = $.extend($.jgrid.defaults, {
            datatype: 'json',
            height: 'auto',
            imgpath: '/Content/jqGrid/themes/basic/images',
            jsonReader: {
                root: "Rows",
                page: "Page",
                total: "Total",
                records: "Records",
                repeatitems: <strong>false</strong>,
                userdata: "UserData",
                id: "Id"
            },
            loadui: "block",
            mtype: 'GET',
            multiboxonly: <strong>true</strong>,
            rowNum: 20,
            rowList: [10, 20, 50],
            url: "ListGridData.json",
            viewrecords: <strong>true</strong>
        });
    }</code></pre>
</blockquote>
<p>In addition to setting <code>repeatitems</code>, telling the grid to expect the capitalization I mentioned above, this code also sets the grid theme and other options we want to be consistent throughout the application. One important property set in the <code>jsonReader </code>property is <code>id</code>. The value supplied is the name of a column in the returned data which contains a unique ID for the row. You can supply any name you want to, and the type of the property can be just about anything serializable, but it is important that the data you return to the grid contains some unique ID. All of the types in our Entity Framework model contain a unique ID called "<code>Id</code>", so we set this in our defaults for the grid. If you don&#8217;t have a single operating name for any data you might supply to the grid, you will have to set this value on the individual grids, when you write the JavaScript for the view.</p>
<p>Now I can write a method which takes a PagedList and transforms it into jqGrid data:</p>
<blockquote>
<pre><code>        /// &lt;summary&gt;
        /// Converts a paged list into a format suitable for the JqGrid component, when
        /// serialized to JSON. Use this method when returning data that the JqGrid component will
        /// fetch via AJAX. Take the result of this method, and then serialize to JSON. This method
        /// will also apply paging to the data.
        /// &lt;/summary&gt;
        /// &lt;typeparam name="T"&gt;The type of the element in baseList. Note that this type should be
        /// an anonymous type or a simple, named type with no possibility of a cycle in the object
        /// graph. The default JSON serializer will throw an exception if the object graph it is
        /// serializing contains cycles.&lt;/typeparam&gt;
        /// &lt;param name="list"&gt;The list of records to display in the grid.&lt;/param&gt;
        /// &lt;param name="userData"&gt;Arbitrary data to be returned to the grid along with the row data.
        /// Leave null if not using. Must be serializable to JSON!&lt;/param&gt;
        /// &lt;returns&gt;A structure containing all of the fields required by the JqGrid. You can then call
        /// a JSON serializer, passing this result.&lt;/returns&gt;
        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the grid component we use.")]
        <strong>public static </strong>JqGridData ToJqGridData&lt;T&gt;(<strong>this </strong>PagedList&lt;T&gt; list, <strong>object </strong>userData)
        {
            <strong>return new </strong>JqGridData()
            {
                Page = list.PageIndex,
                Records = list.TotalItemCount,
                Rows = from record in list
                       select record,
                Total = list.PageCount,
                UserData = userData
            };
        }</code></pre>
</blockquote>
<p>That&#8217;s getting somewhere, but it&#8217;s not yet enough to let me write the action method I showed above. For that, I need to wrap up the PagedList inside the action so that I can pass the arguments from the grid directly, without having to construct a new PagedList inside of every action method which supplies data to a grid. So I build on the method above:</p>
<pre><code>        /// &lt;summary&gt;
        /// Converts a queryable expression into a format suitable for the JqGrid component, when
        /// serialized to JSON. Use this method when returning data that the JqGrid component will
        /// fetch via AJAX. Take the result of this method, and then serialize to JSON. This method
        /// will also apply paging to the data.
        /// &lt;/summary&gt;
        /// &lt;typeparam name="T"&gt;The type of the element in baseList. Note that this type should be
        /// an anonymous type or a simple, named type with no possibility of a cycle in the object
        /// graph. The default JSON serializer will throw an exception if the object graph it is
        /// serializing contains cycles.&lt;/typeparam&gt;
        /// &lt;param name="baseList"&gt;The list of records to display in the grid.&lt;/param&gt;
        /// &lt;param name="currentPage"&gt;A 1-based index indicating which page the grid is about to display.&lt;/param&gt;
        /// &lt;param name="rowsPerPage"&gt;The maximum number of rows which the grid can display at the moment.&lt;/param&gt;
        /// &lt;param name="orderBy"&gt;A string expression containing a column name and an optional ASC or
        /// DESC. You can, separate multiple column names as with SQL.&lt;/param&gt;
        /// &lt;param name="searchQuery"&gt;The value which the user typed into the search box, if any. Can be
        /// null/empty.&lt;/param&gt;
        /// &lt;param name="searchColumns"&gt;An array of strings containing the names of properties in the
        /// element type of baseList which should be considered when searching the data for searchQuery.&lt;/param&gt;
        /// &lt;param name="userData"&gt;Arbitrary data to be returned to the grid along with the row data. Leave
        /// null if not using. Must be serializable to JSON!&lt;/param&gt;
        /// &lt;returns&gt;A structure containing all of the fields required by the JqGrid. You can then call
        /// a JSON serializer, passing this result.&lt;/returns&gt;
        [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the JavaScript component this type is designed to support.")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Jq",
            Justification = "JqGrid is the correct name of the grid component we use.")]
        <strong>public static </strong>JqGridData ToJqGridData&lt;T&gt;(<strong>this </strong>IQueryable&lt;T&gt; baseList,
            <strong>int </strong>currentPage,
            <strong>int </strong>rowsPerPage,
            <strong>string </strong>orderBy,
            <strong>string </strong>searchQuery,
            IEnumerable&lt;<strong>string</strong>&gt; searchColumns,
            <strong>object </strong>userData)
        {
            <strong>var </strong>filteredList = ListAddSearchQuery(baseList, searchQuery, searchColumns);
            <strong>var </strong>pagedModel = <strong>new </strong>PagedList&lt;T&gt;(filteredList.OrderBy(orderBy), currentPage, rowsPerPage);
            <strong>return </strong>pagedModel.ToJqGridData(userData);
        }</code></pre>
<p>Now you see that string array (IEnumerable, actually) again. JqGrid supports sorting and searching, and so do I. Like Phil, I suggest using Microsoft Dynamic LINQ in order to take the field names that jqGrid passes and turn them into a sorted, filtered, result set. ListAddSearchQuery is a (longish) method which takes a search string and a list of columns to search and turns them into a Dynamic LINQ expression and applies it to the base list. Unfortunately, search is kind of application-specific. In some applications you might want to search different columns in different ways. Some applications might want "Google-style" searching. It kind of depends upon what you&#8217;re doing. So although I will supply the source code for this method when I make the demo project available, I cannot promise that it will be useful for <em>your </em>application. Feel free to substitute your own method here.</p>
<p>It turns out both methods (the one which takes a <code>PagedList </code>and the one which takes an <code>IQueryable</code>) are useful. Generally, I use the method which takes an <code>IQueryable</code>. But every once in a while I want to do something to the data I&#8217;m about to supply to the grid before the grid sees it, but after paging, like transform a single page of results in some way. In this case, the action builds up a <code>PagedList</code>, uses that to reduce to one page of data, modifies the results in whatever way is appropriate, and then calls the <code>PagedList </code>extension. I&#8217;ve also written additional overloads to both methods which do not have a <code>userData </code>argument, since it is very seldomly used. <code>userData</code>, as the name suggests, is an additional bit of data you can return to the grid with your result set for use in grid event handlers when loading a fresh page of data. Since it&#8217;s of type object, you can put as much data in there as you need to, so long as it&#8217;s serializable to JSON. In practice, though, we rarely use this feature of the grid.</p>
<p>With these methods, it is easy to write actions as concise as the code I showed at the beginning of this post. Just get a list from somewhere and call ToJqGridData, passing information about which page to display, how to sort, etc.</p>
<p>In a future post, I will tie this all together into a demo application.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38212&amp;akst_action=share-this" onclick="akst_share('38212', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F15%2F38212%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+LINQ+Extensions'); return false;" title="Post to del.icio.us, etc." id="akst_link_38212" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20LINQ%20Extensions&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F15%2F38212%2F" id="akst_email_38212" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Using jqGrid with ASP.NET MVC: Introduction</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/14/38200/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/14/38200/#comments</comments>
    <pubDate>Tue, 14 Apr 2009 11:28:03 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38200</guid>
    <description><![CDATA[This is the first post in a short series on using the jqGrid jQuery plug-in with ASP.NET MVC. In this short introduction I will describe the plug-in, list some of its strengths and weaknesses, and explain why we selected it for our MVC applications. In the next few days, I will give detailed information about [...]]]></description>
      <content:encoded><![CDATA[<p>This is the first post in a short series on using the <a href="http://www.trirand.com/blog/">jqGrid</a> jQuery plug-in with ASP.NET MVC. In this short introduction I will describe the plug-in, list some of its strengths and weaknesses, and explain why we selected it for our MVC applications. In the next few days, I will give detailed information about how to use the grid in your own applications.</p>
<p>jqGrid provides a nice-looking grid with built-in features such as sorting, editing, search, drill-down, tree lists, and more. It is based upon jQuery and integrates well with ASP.NET MVC. <a href="http://www.trirand.com/blog/?page_id=154">The grid is dual-licensed under both the GPL and MIT licenses</a> (just like jQuery), so it can fit well into both commercial and open-source projects.</p>
<p><a href="/files/2009/04/jqgrid_1166.png"><img src="/files/2009/04/jqgrid_1166.png" alt="jqGrid with sub-grid" width="660" height="277" /></a></p>
<p>If you want to display tabular (grid) data with paging in an ASP.NET MVC application, there are essentially three choices:</p>
<ol>
<li>You can write your own grid components using HTML tables, links, manually-implemented paging, etc. This is actually less work than it might seem at first, and the first release of our ASP.NET MVC software did just this. But our own implementation lacked some of the visual flair of some of the third-party components, and avoided solving some of the harder problems, like in-line editing. Still, it was much easier than I expected, and worked well enough for our initial release.</li>
<li>You can use a commercial component designed for ASP.NET. However, many commercial grid components don&#8217;t work well with MVC. Telerik has MVC demos available for their grid, and Developer Express has said that they intend to support MVC to some degree in the future. Even when the commercial components do support MVC at all, they don&#8217;t tend to make all of their features available in MVC applications, owing to the fundamental difference between the way ASP.NET MVC and "plain" ASP.NET work. If you are building a Web application on ASP.NET MVC, I would never recommend buying an ASP.NET component unless the vendor for that component is fully committed to supporting MVC. <em>You cannot presume that any given ASP.NET component will work at all with MVC unless the vendor explicitly supports this.</em></li>
<li>You can use a grid component which has no knowledge of ASP.NET at all. There are quite a number of these, generally built within the framework of one of the popular JavaScript libraries, and it is, ironically, easier to use one of them within ASP.NET MVC application than it is to use a grid component designed for ASP.NET (but not necessarily MVC).</li>
</ol>
<p>As I said, we ended up choosing jqGrid. We were strongly influenced by the fact that we already use jQuery extensively in our application. There are several grid plug-ins available for jQuery. jqGrid has a number of advantages over the others I&#8217;ve seen, however:</p>
<ul>
<li>Supports three different models for editing data within the grid: Single-cell editing, in-line row editing, and editing within a pop-up form.</li>
<li>Unlike some of the other jQuery grid plug-ins, jqGrid has <a href="http://www.secondpersonplural.ca/jqgriddocs/index.htm">decent documentation</a> and <a href="http://trirand.com/jqgrid/jqgrid.html">a large number of demos with source code</a>.</li>
<li>You can display a simple grid, a "sub grid" (drill down), or a treeview.</li>
<li>AJAX paging is supported in a number of different formats, including JSON, XML, or JavaScript objects via a custom function.</li>
<li>The grid is updated very regularly, and <a href="http://www.trirand.com/jqgrid35/jqgrid.html">a new version, with support for the jQuery UI theming library</a> is under active development right now.</li>
<li>Tracing through the grid source code is quite easy to do with Firebug, which is useful for figuring out things which aren&#8217;t quite covered by the documentation.</li>
</ul>
<p>The grid also has a few downsides:</p>
<ul>
<li>The API is a bit of a mess. Capitalization (significant, in JavaScript) is so varied that it seems almost random. Portions of the code were clearly written by different people with limited collaboration with the original author of the grid. There is no consistent naming convention, and similar functionality is sometimes invoked in wildly different ways. For example, you set the grid height with a custom method, <code>setGridHeight</code>, instead of the jQuery method <code>height</code>. But you reload the grid&#8217;s data with a jQuery method, <code>trigger</code>, passing the string <code>"reloadGrid"</code> as an argument. It&#8217;s a good thing the grid has decent documentation and includes source code, because you&#8217;re going to need them. The API is just not discoverable.</li>
<li>Although the grid has quite a number of options for editing, it doesn&#8217;t necessarily play well with some of the other tools you may want to use in the context of editing, such as <a title="http://blogs.teamb.com/craigstuntz/2009/01/15/37923/" href="http://blogs.teamb.com/craigstuntz/2009/01/15/37923/">jQuery validation</a>. (For starters, the in-line row editing doesn&#8217;t actually use an HTML form.) The three different editing modes (single-cell, in-line row editing, and editing in a form) use different source modules, different configuration options, and work differently. Doing editing in a way not explicitly supported by the grid can be challenging.</li>
<li>Variable names in the source code use a lot of single letter and two letter abbreviations. This is quite common in JavaScript libraries, but it does make the source code a bit challenging to read.</li>
<li>Although <a href="http://www.trirand.com/blog/?page_id=154">there is both free and paid support available</a>, there is not a commercial company standing behind the grid. So don&#8217;t expect round-the-clock support, a toll-free phone number, etc.</li>
</ul>
<p>After a good deal of experimentation with several grids, we decided to use jqGrid because it has considerably more features than every other grid we examined (when used in MVC application), and because we didn&#8217;t find any of its limitations to be show stoppers.</p>
<p>The next post in this series is <a href="http://blogs.teamb.com/craigstuntz/2009/04/15/38212/">LINQ Extensions</a>. There, I show an extension method for <code>IQueryable&lt;T&gt;</code> which returns data suitable for the grid, without having to know anything about the type <code>T.</code></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38200&amp;akst_action=share-this" onclick="akst_share('38200', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F14%2F38200%2F', 'Using+jqGrid+with+ASP.NET+MVC%3A+Introduction'); return false;" title="Post to del.icio.us, etc." id="akst_link_38200" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Using%20jqGrid%20with%20ASP.NET%20MVC%3A%20Introduction&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F14%2F38200%2F" id="akst_email_38200" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Do You Recognize Math When You See It?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/07/38190/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/07/38190/#comments</comments>
    <pubDate>Tue, 07 Apr 2009 10:34:14 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38190</guid>
    <description><![CDATA[Jeff Atwood says:
On the other hand, I have not found in practice that programmers need to be mathematically inclined to become great software developers.  Quite the opposite, in fact. This does depend heavily on what kind of code you&#8217;re writing, but the vast bulk of code that I&#8217;ve seen consists mostly of the "balancing [...]]]></description>
      <content:encoded><![CDATA[<p><a title="Should Competent Programmers be &quot;Mathematically Inclined&quot;?" href="http://www.codinghorror.com/blog/archives/001249.html">Jeff Atwood says</a>:</p>
<blockquote><p>On the other hand, <strong>I have not found <em>in practice</em> that programmers need to be mathematically inclined to become great software developers</strong>.  Quite the opposite, in fact. This does depend heavily on what kind of code you&#8217;re writing, but the vast bulk of code that <em>I&#8217;ve</em> seen consists mostly of the "balancing your checkbook" sort of math, nothing remotely like what you&#8217;d find in the average college calculus textbook, even.</p>
<pre>{
  i = j++ / (x + v);
}</pre>
<p>Not exactly the stuff mathletes are made of.</p></blockquote>
<p>Arithmetic is one kind of math. It is relatively common in elementary math classes, and <em>relatively </em>uncommon in programming. Does Jeff&#8217;s example look like the "vast bulk of code <em>you&#8217;ve </em>seen?" It certainly doesn&#8217;t look like the vast bulk of code <em>I&#8217;ve </em>seen.</p>
<p>On the other hand, I do see a good bit of:</p>
<ul>
<li>Relational database queries (<a href="http://www.vocw.edu.vn/content/m10536/latest/">relational algebra</a>)</li>
<li>LINQ (<a href="http://mathworld.wolfram.com/Functor.html">functors</a>)</li>
<li>Composition of lambda expressions (<a href="http://mathworld.wolfram.com/LambdaCalculus.html">lambda calculus</a>, of course)</li>
<li>Set operations and logical operators (<a href="http://mathworld.wolfram.com/SetTheory.html">set theory</a>)</li>
<li>Etc.</li>
</ul>
<p>That&#8217;s by no means a comprehensive list. For example, every general-purpose programming language I&#8217;ve ever used would not exist without the <a href="http://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis">Church-Turing thesis</a>. But I didn&#8217;t include that, since most people don&#8217;t do programming language design.</p>
<p>All programmers work with mathematical systems day in and day out, whether we recognize them or not. Perhaps the ability to recognize math when we see it will help us better evaluate the importance of understanding it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38190&amp;akst_action=share-this" onclick="akst_share('38190', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F07%2F38190%2F', 'Do+You+Recognize+Math+When+You+See+It%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38190" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Do%20You%20Recognize%20Math%20When%20You%20See%20It%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F07%2F38190%2F" id="akst_email_38190" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Reminder: Mike Rozlog to Speak to Columbus Architecture Group</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/04/06/38188/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/04/06/38188/#comments</comments>
    <pubDate>Mon, 06 Apr 2009 15:28:29 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38188</guid>
    <description><![CDATA[Mike Rozlog, the product manager for the JBuilder and 3rdRail products for Embarcadero, will be speaking to the Columbus Architecture Group tonight at 6:00 p.m., on the subject of software archaeology. For more information on the topic, here is a slide deck for one of his previous presentations on the subject, and here&#8217;s a video [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a>, the product manager for the JBuilder and 3rdRail products for <a href="http://www.embarcadero.com/">Embarcadero</a>, will be speaking to the <a href="http://www.colarc.org/2009/03/guest-speaker-at-april-6th-meeting.html">Columbus Architecture Group <em>tonight </em>at 6:00 p.m.</a>, on the subject of <a href="http://www.embarcadero.com/solutions/software_archeology.php">software archaeology</a>. For more information on the topic, here is <a href="http://blogs.embarcadero.com/files/2007/12/radstudiowebinar_192.pdf">a slide deck for one of his previous presentations on the subject</a>, and <a href="http://cc.embarcadero.com/Item/26427">here&#8217;s a video replay</a>.</p>
<p><strong>Update:</strong> Attendee Bill Melvin wrote <a title="COLARC Meeting - April 2009" href="http://www.bluecog.com/blog/2009/04/07/colarc-meeting-april-2009/">a short summary of the presentation</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38188&amp;akst_action=share-this" onclick="akst_share('38188', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F06%2F38188%2F', 'Reminder%3A+Mike+Rozlog+to+Speak+to+Columbus+Architecture+Group'); return false;" title="Post to del.icio.us, etc." id="akst_link_38188" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Reminder%3A%20Mike%20Rozlog%20to%20Speak%20to%20Columbus%20Architecture%20Group&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F04%2F06%2F38188%2F" id="akst_email_38188" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Designed as Designer</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/31/38153/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/31/38153/#comments</comments>
    <pubDate>Tue, 31 Mar 2009 13:04:52 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38153</guid>
    <description><![CDATA[Have you ever ridden a horse? When you drive the car, the process goes something like this:

Decide where you want to go.
Aim the car in that direction.
Get there.

It&#8217;s different when you ride a horse. In that case the process is more like:

Decide where you want to go.
Communicate your intention to the horse.
Arrive at some hybrid [...]]]></description>
      <content:encoded><![CDATA[<p>Have you ever ridden a horse? When you drive the car, the process goes something like this:</p>
<ol>
<li>Decide where you want to go.</li>
<li>Aim the car in that direction.</li>
<li>Get there.</li>
</ol>
<p>It&#8217;s different when you ride a horse. In that case the process is more like:</p>
<ol>
<li>Decide where you want to go.</li>
<li>Communicate your intention to the horse.</li>
<li>Arrive at some hybrid of where you want to go and where the horse wants to go.</li>
<li>Return to step (1). Repeat.</li>
</ol>
<p>Now, which of those two would you find more analogous to software architecture? Does that sound like a silly question? The reason that I ask is that I read a paper last night which argues in a persuasive but decidedly unconventional manner that <em>the things you design </em>have, for lack of a better word, intention. In other words, building a cathedral, or a software application is more like riding a horse than driving a car.</p>
<p>The paper is called <a href="http://dreamsongs.org/DesignedAsDesigner.html">Designed as Designer</a>, by <a href="http://en.wikipedia.org/wiki/Richard_Gabriel">Richard P. Gabriel</a>. As technical papers go, this one is unusual to say the least. It was written as a response to <a href="http://www.oopsla.org/oopsla2007/index.php?page=podcasts/">an address by Fred Brooks at OOPSLA 2007</a>, during his keynote. In the address, Brooks stated:</p>
<blockquote><p>If we look back then at the 19th century and the things that happened—the cartwright and the textile machinery, Stephenson (the train), Brunel&#8217;s bridges and railway, Edison, Ford, the Wright brothers, etc.—these were very largely the designs of single designers or, in the case of the Wright brothers, pairs.</p></blockquote>
<p>Gabriel disputes this idea, and chooses an unexpected way of making his case. <a href="http://dreamsongs.org/Books.html">Gabriel is a published author </a>both in the fields of computer science and writing/poetry. The paper draws as much from his experience in the latter field as the former—there is considerably more poetry quoted in the paper than source code. He also manages to weave in, <em>with some relevance, no less</em>, baseball statistics.</p>
<p>The general outline of the paper is as follows: First, there is a running, fictional narrative about a child named Pippo who observes the construction of the <a href="http://www.duomofirenze.it/storia/storia_eng.htm">cathedral of Firenze</a>. Next, Gabriel addresses Brooks&#8217;s point directly. He discusses the relationship between poets T.S. Eliot and Ezra Pound in the evolution of Eliot&#8217;s masterpiece <a href="http://www.bartleby.com/201/1.html"><em>The Waste Land</em></a>. The middle, and longest, section of the paper is an explanation and example of a theory of poetry he has developed based around an almost algorithmic approach to classifying a given text as either poetry or ordinary writing. Contrasting an early version of a published column with a later revision to same, he asserts that the structure of the earlier version leads the poet into the later revision. I should add here that even though I really like poetry, I find his analysis a bit academic for my taste. Returning to the Cathedral of Firenze, Gabriel shows that many people were involved in its design and construction, and that the Cathedral form itself had a bigger impact on the final design than the architect. Then he uses statistical analysis of the career of Roger Maris to show that luck, as much as skill, played a role in Maris&#8217;s exceeding Babe Ruth&#8217;s home run record.</p>
<p>The final section of the paper includes, almost shockingly at this point, discussion of computer science and one small example of (Lisp) source code. He relates the story of how Gerry Sussman and Guy Steele discovered how two mechanisms they were studying turned out to be exactly the same thing by implementing both of them separately and noticing later that the source code was identical.</p>
<p>If all this sounds a bit, well, crazy, it isn&#8217;t. <a href="http://www.oopsla.org/oopsla2008/program-overview/essays.html">The paper was presented at OOPSLA 2008</a>. I&#8217;m not above a bit of <em>schadenfreude</em>, but this is definitely a "laugh with him" rather than "laugh at him" paper. If you have ever had the experience of designing a system, and then uncovering necessary changes in the system when you try to use your design, then you have some idea of what he&#8217;s getting at.</p>
<p>I am also reminded, more than a little bit, of Michael Pollan&#8217;s book, <a href="http://www.amazon.com/gp/product/0375760393?ie=UTF8&amp;tag=learningtowhi-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0375760393">The Botany of Desire</a><img style="border:none !important;margin:0px !important" src="http://www.assoc-amazon.com/e/ir?t=learningtowhi-20&amp;l=as2&amp;o=1&amp;a=0375760393" border="0" alt="" width="1" height="1" />, which calls the evolution of the humans and plants "co-evolutionary," and questions who has domesticated whom. Again, we don&#8217;t tend to think of plants as having "intention," but maybe the question should be, "just what is intention, really?" So all in all, it&#8217;s a fascinating read.</p>
<p>That said, it seems to me that, to some extent, Brooks and Gabriel may be talking past each other. Surely, Brooks can&#8217;t be under the delusion that the Wright brothers invented the airplane in a vacuum? Surely, Gabriel wouldn&#8217;t presume that he is? Much of Brooks&#8217;s writing focuses on organizational support for creativity. Indeed, Brooks, to me, seems almost to take creativity as a given, more so than examining what it is and what makes it tick. Gabriel seems to be on the other side of this coin, examining the nature of creativity, rather than how to make it work in a large organization.</p>
<p>Both points of view are worth reading, I think.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38153&amp;akst_action=share-this" onclick="akst_share('38153', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F31%2F38153%2F', 'Designed+as+Designer'); return false;" title="Post to del.icio.us, etc." id="akst_link_38153" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Designed%20as%20Designer&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F31%2F38153%2F" id="akst_email_38153" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>URIs Should Be Persistent</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/30/38145/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/30/38145/#comments</comments>
    <pubDate>Mon, 30 Mar 2009 12:02:54 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38145</guid>
    <description><![CDATA[When you are creating a new URI for a site you are building, give it a lot of thought. You should aim to design a URI which can last forever. Of course, this is not news. Jakob Nielsen said it 10 years ago. But in the intervening 10 years, we&#8217;ve gone from URIs which typically [...]]]></description>
      <content:encoded><![CDATA[<p>When you are creating a new URI for a site you are building, give it a lot of thought. You should aim to design a URI which can last forever. Of course, this is not news. <a title="URL as UI" href="http://www.useit.com/alertbox/990321.html">Jakob Nielsen said it 10 years ago</a>. But in the intervening 10 years, we&#8217;ve gone from URIs which typically used to look something like this:</p>
<blockquote><p><code>http://www.example.com/foo.html</code></p></blockquote>
<p>&#8230;which is fine, because if you go to such a link, you probably really will get HTML back, to URIs which (often) look something like this:</p>
<blockquote><p><code>http://www.example.com/foo.php</code></p></blockquote>
<p>&#8230;which, <a title="The Web Is Just Text" href="http://blogs.teamb.com/craigstuntz/2009/02/16/38024/">as I noted in a previous post</a>, is a lie. Actually, it&#8217;s worse than a lie; it&#8217;s poor encapsulation. What happens when you come to your senses and stop using PHP? Now you URIs have to change, which means you get to either create redirects for that abomination or break every link to your site. One of the things we&#8217;ve learned from the success of Google is that the information encoded in the links between sites is nearly as important as the information on the sites itself.</p>
<p><em>The web is dynamic. It has to be, because it is too big to compile. </em>And so the same concerns we have when writing code and dynamic languages often apply to creating a web site, whether you use a dynamic language or not. You need to choose very good names, because if you ever need to change them you will either break stuff or have a substantial job on your hands correcting every reference to the name you&#8217;ve changed, including references you don&#8217;t personally control.</p>
<p>So I&#8217;m going to propose a general rule, which states, "<strong>Any URI which allows an informed developer to discern the technology used to serve the result is probably broken.</strong>" The resources you are serving, if they are at all valuable to the user, will probably last longer than the implementation you use to serve them.</p>
<p>Of course, choosing good names is hard. <a title="Naming is Hard" href="http://blog.stackoverflow.com/2009/03/it-stack-overflow-update-naming-is-hard/">I read a great quote the other day</a>:</p>
<blockquote><p>There are only two hard things in Computer Science: cache invalidation and naming things. -Phil Karlton</p></blockquote>
<p>Also, even after you&#8217;ve chosen a good URI, you may have to do extra work to make it functional. If routing is not built into the technology stack you&#8217;re using, you may have to implement a URL rewriter to make your persistent URIs functional. It&#8217;s worth the effort to do so.</p>
<p><strong>Late update</strong>: Thank you to commentor <a href="http://www.stecki.de/">Stecki</a> for <a href="http://blogs.teamb.com/craigstuntz/2009/03/30/38145/#comment-5058">the link to</a> the following article: <a href="http://www.w3.org/Provider/Style/URI">Cool URIs don&#8217;t change</a>, by Tim Berners-Lee. Well said.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38145&amp;akst_action=share-this" onclick="akst_share('38145', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F30%2F38145%2F', 'URIs+Should+Be+Persistent'); return false;" title="Post to del.icio.us, etc." id="akst_link_38145" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=URIs%20Should%20Be%20Persistent&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F30%2F38145%2F" id="akst_email_38145" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Why Has the Size of TObject Doubled In Delphi 2009?</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/25/38138/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/25/38138/#comments</comments>
    <pubDate>Wed, 25 Mar 2009 11:23:00 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38138</guid>
    <description><![CDATA[Because it has a new feature.
Mason Wheeler noticed that TObject.InstanceSize returns 8 (bytes). It turns out that this is new in Delphi 2009; in previous releases, TObject.InstanceSize returned 4. But when you look at the definition of TObject in System.pas, you don&#8217;t see any fields declared at all.
Four out of the eight bytes are consumed [...]]]></description>
      <content:encoded><![CDATA[<p>Because it has a new feature.</p>
<p><a title="TURBU" href="http://turbu-rpg.com/">Mason Wheeler</a> noticed that <a title="What data does a TObject contain?" href="http://stackoverflow.com/questions/679022/what-data-does-a-tobject-contain">TObject.InstanceSize returns 8</a> (bytes). It turns out that this is new in Delphi 2009; in previous releases, TObject.InstanceSize returned 4. But when you look at the definition of TObject in System.pas, you don&#8217;t see any fields declared at all.</p>
<p>Four out of the eight bytes are consumed by the <acronym title="Virtual Method Table">VMT</acronym>; this has been true since the first version of Delphi. You can read more about that in <a title="The Delphi Object Model" href="http://oreilly.com/catalog/delphi/chapter/ch02.html">this chapter from <em>Delphi In A Nutshell</em></a>, which is old, but still accurate insofar as the VMT is concerned.</p>
<p>But what about the remaining four bytes? I didn&#8217;t remember the answer, but I enjoy a good puzzle, so I took a closer look at the source code for TObject. While poking around in System.pas, I happened to notice the following constants:</p>
<blockquote>
<pre><code><span style="color: #008000"><em>{ Hidden TObject field info }</em></span>
hfFieldSize          = <span style="color: #0000ff">4</span>;
hfMonitorOffset      = <span style="color: #0000ff">0</span>;</code></pre>
</blockquote>
<p>OK, that explains the four bytes, but what is this used for? Searching for <code>hfFieldSize</code> yielded the answer:</p>
<blockquote>
<pre><code><strong>class function</strong> TMonitor.GetFieldAddress(AObject: TObject): PPMonitor;
<strong>begin</strong>
  Result := PPMonitor(Integer(AObject) + AObject.InstanceSize - hfFieldSize + hfMonitorOffset);
<strong>end</strong>;</code></pre>
</blockquote>
<p>So any object <em>can </em>have a reference to a TMonitor instance, and that reference is as big as a pointer on the target CPU. That reminded me of <a title="Lock my Object… Please!" href="http://blogs.embarcadero.com/abauer/2008/02/19/38856">Allen Bauer&#8217;s long series of blog posts last year on the "Delphi Parallel Library,"</a> which discuss the TMonitor class in detail. He notes:</p>
<blockquote><p>The TMonitor class<em> [...] </em>is now tied directly to any TObject instance or derivative (which means <em>any</em> instance of a Delphi <strong>class</strong>).  <em>[...] </em>For Tiburón <em>[a.k.a. Delphi 2009]</em>, you merely need to call System.TMonitor.Enter(&lt;obj&gt;); or System.TMonitor.Exit(&lt;obj&gt;); among the other related methods.</p></blockquote>
<p>The ability to lock any object is a good feature to have, especially in a multi-CPU, multi-core world. So I&#8217;m happy to spend the extra four bytes to get this feature. But I do find the implementation a bit mysterious. Why not just declare an actual field in TObject? I guess one reason would be to reduce the chance of a conflict with existing code. Another possible reason would be to enforce TMonitor&#8217;s contract; by obfuscating access to the field, you reduce the chances that an uninformed programmer performs actions on the field which break the contract. But these are just guesses. I don&#8217;t know why the Delphi team settled on this implementation. I presume they have some good reason.</p>
<p><strong>Update:</strong> In comments, <a href="http://blogs.codegear.com/abauer">Allen Bauer</a> explains <a href="http://blogs.teamb.com/craigstuntz/2009/03/25/38138/#comment-4937">the reasons for this implementation</a>:</p>
<blockquote><p>The reason for always placing the monitor reference field at the end of the object instance is mainly for backward compatibility. I didn’t want to alter the layout of objects in case there was some code out there that depended upon it. Also, by hiding the implementation the chance of inadvertent mucking with the monitor data was reduced and therefore it increased the overall safety of using it.</p>
<p>If you look closely at what happens on descendant instances, the monitor field is <strong>always </strong>the last field of the instance. This happens because the compilers (Delphi &amp; C++) ensure that the field is allocated as the last step in the process of laying out the class instance. By doing this, an object laid out in pre-Delphi 2009 will be laid out exactly the same in Delphi 2009 except there is now an extra trailing pointer-sized field.</p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38138&amp;akst_action=share-this" onclick="akst_share('38138', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F25%2F38138%2F', 'Why+Has+the+Size+of+TObject+Doubled+In+Delphi+2009%3F'); return false;" title="Post to del.icio.us, etc." id="akst_link_38138" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Why%20Has%20the%20Size%20of%20TObject%20Doubled%20In%20Delphi%202009%3F&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F25%2F38138%2F" id="akst_email_38138" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>InterBase 2009 Hotfix Update 2</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/23/38135/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/23/38135/#comments</comments>
    <pubDate>Mon, 23 Mar 2009 23:49:31 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38135</guid>
    <description><![CDATA[IB 2009 Hotfix Update 2 is available for download, and includes many bug fixes.
]]></description>
      <content:encoded><![CDATA[<p>IB 2009 Hotfix Update 2 is <a title="InterBase Registered User Downloads" href="http://cc.embarcadero.com/reg/interbase">available for download</a>, and includes <a title="InterBase 2009 Hotfix Update 2 Readme (version 9.0.2.369)" href="http://edn.embarcadero.com/article/39435#6ResolvedDefects">many bug fixes</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38135&amp;akst_action=share-this" onclick="akst_share('38135', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38135%2F', 'InterBase+2009+Hotfix+Update+2'); return false;" title="Post to del.icio.us, etc." id="akst_link_38135" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=InterBase%202009%20Hotfix%20Update%202&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38135%2F" id="akst_email_38135" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>What ASP.NET MVC Did Learn from Rails</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/23/38130/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/23/38130/#comments</comments>
    <pubDate>Mon, 23 Mar 2009 19:30:27 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38130</guid>
    <description><![CDATA[This morning, I saw two different posts from Rails developers who were newly learning ASP.NET MVC, both bemoaning the fact that ASP.NET MVC does not supply/force upon you one particular ORM. The dependency on ActiveRecord is, to my way of thinking, a shortcoming of Rails, which the Rails community is presently doing an exceptional job [...]]]></description>
      <content:encoded><![CDATA[<p>This morning, I saw two different posts from <a title=".NET MVC vs Ruby on Rails" href="http://www.tokumine.com/2009/03/21/net-mvc-vs-ruby-on-rails/">Rails developers who were newly learning ASP.NET MVC</a>, both <a title="What ASP.NET MVC Can Learn From Ruby on Rails" href="http://www.kevinwilliampang.com/post/What-ASPNET-MVC-Can-Learn-From-Ruby-on-Rails.aspx">bemoaning the fact that ASP.NET MVC does not supply</a>/force upon you one particular ORM. The <a title="Rails without ActiveRecord" href="http://blog.lathi.net/articles/2007/08/08/rails-without-activerecord">dependency on ActiveRecord</a> is, to my way of thinking, a shortcoming of Rails, <a title="Lightweight Frameworks, Again" href="http://blogs.teamb.com/craigstuntz/2008/12/26/37874/">which the Rails community is presently doing <em>an exceptional job of fixing</em></a>. The best way to learn from that mistake is to not repeat it.</p>
<p>Yes, it is true that ASP.NET MVC does not force you to use one particular ORM. Yes, that means that you&#8217;re going to have to expend some thought, and quite possibly even effort, deciding which one is appropriate for you. It will not be sufficient to read a blog post about the Entity Framework from somebody who tried it once and another blog post about NHibernate from somebody who saw a screencast about it and then conclude that there are no workable solutions in the world.</p>
<p>But it&#8217;s worth the effort, because you have a big reward in store: Whatever choice you make will work just fine with ASP.NET MVC. Because the framework has no dependencies whatsoever on any ORM, all ORMs work equally well. You get to choose the best tool for your data access needs without worrying that your web framework will reject it.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38130&amp;akst_action=share-this" onclick="akst_share('38130', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38130%2F', 'What+ASP.NET+MVC+Did+Learn+from+Rails'); return false;" title="Post to del.icio.us, etc." id="akst_link_38130" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=What%20ASP.NET%20MVC%20Did%20Learn%20from%20Rails&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F23%2F38130%2F" id="akst_email_38130" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Mike Rozlog to Speak to Columbus Architecture Group</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/20/38126/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/20/38126/#comments</comments>
    <pubDate>Fri, 20 Mar 2009 19:41:03 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[CodeRage]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38126</guid>
    <description><![CDATA[Mike Rozlog, the product manager for the JBuilder and 3rdRail products for Embarcadero, will be speaking to the Columbus Architecture Group on Monday, April 6, at 6:00 p.m., on the subject of software archaeology. For more information on the topic, here is a slide deck for one of his previous presentations on the subject, and [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a>, the product manager for the JBuilder and 3rdRail products for <a href="http://www.embarcadero.com/">Embarcadero</a>, will be speaking to the <a href="http://www.colarc.org/2009/03/guest-speaker-at-april-6th-meeting.html">Columbus Architecture Group on Monday, April 6, at 6:00 p.m.</a>, on the subject of <a href="http://www.embarcadero.com/solutions/software_archeology.php">software archaeology</a>. For more information on the topic, here is <a href="http://blogs.embarcadero.com/files/2007/12/radstudiowebinar_192.pdf">a slide deck for one of his previous presentations on the subject</a>, and <a href="http://cc.embarcadero.com/Item/26427">here&#8217;s a video replay</a>.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38126&amp;akst_action=share-this" onclick="akst_share('38126', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F20%2F38126%2F', 'Mike+Rozlog+to+Speak+to+Columbus+Architecture+Group'); return false;" title="Post to del.icio.us, etc." id="akst_link_38126" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Mike%20Rozlog%20to%20Speak%20to%20Columbus%20Architecture%20Group&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F20%2F38126%2F" id="akst_email_38126" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>ASP.NET Routing and ASP.NET MVC</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/18/38085/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/18/38085/#comments</comments>
    <pubDate>Wed, 18 Mar 2009 13:02:58 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38085</guid>
    <description><![CDATA[.NET 3.5 SP1 introduced ASP.NET Routing. This feature is primarily used by ASP.NET MVC and Dynamic Data. Routing is actually a very simple feature; here is what it does:

Stores a list of routes.
Translates an incoming URI into lists of values and tokens, and passes those lists to the handler specified on the route. In the [...]]]></description>
      <content:encoded><![CDATA[<p>.NET 3.5 SP1 introduced ASP.NET Routing. This feature is primarily used by ASP.NET MVC and Dynamic Data. Routing is actually a very simple feature; here is what it does:</p>
<ul>
<li>Stores a list of routes.</li>
<li>Translates an incoming URI into lists of values and tokens, and passes those lists to the handler specified on the route. In the MVC framework, this feature is used to call the appropriate Controller/Action.</li>
<li>Translates a list of values into a URI suitable for inclusion within an HTML page. In the MVC framework, this feature is most commonly used in the <code>Html.RouteLink/ActionLink</code> methods you call to generate a link in your Views.</li>
</ul>
<p>Let&#8217;s examine in more detail how MVC uses Routing, and distinguish between the features of Routing and the MVC framework.</p>
<h2>Components of a URI</h2>
<p>Consider this sample URI:</p>
<p><code>http://www.example.com:80/SiteRoot/Controller/Action?foo=A&amp;bar=B#anchor</code></p>
<p>The individual parts of the URI are:</p>
<ul>
<li>The <strong>scheme </strong>(protocol), <strong>authority </strong>(host), and <strong>port </strong>("<code>http://www.example.com:80</code>" in this sample URI). I will mostly ignore this part in the rest of the post, since Routing doesn&#8217;t deal with it, except to pass it along when necessary.</li>
<li>The <strong>path </strong>("<code>/SiteRoot/</code><code>Controller/Action</code>" in this example). Per the <a title="Generic Syntax" href="http://www.ietf.org/rfc/rfc3986.txt">URI RFC</a>, this part "serves to identify a resource&#8230;" I&#8217;ll talk about what that means in a second.</li>
<li>The <strong>query </strong>("<code>?foo=A&amp;bar=B</code>" in this example). My example uses name/value pairs is the query, because that seems to be the most common case. However, the RFC says that the query can be almost anything, and the purpose of the query is to provide a non-hierarchical means of identifying the resource requested by the user.</li>
<li>The <strong>fragment </strong>("<code>#anchor</code>" in this example). I&#8217;m going to ignore this, since Routing doesn&#8217;t deal with it.</li>
<li>I&#8217;ve omitted some stuff like username/password which is almost never used today.</li>
</ul>
<h2>MapRoute</h2>
<p>Now lets examine a simple case of adding a route to the routing system. This is from the default MVC application template:</p>
<blockquote>
<pre><code>routes.MapRoute(
    <span style="color: #ff0000">"Default"</span>,                                              <span style="color: #339966">// Route name</span>
    <span style="color: #ff0000">"{controller}/{action}/{id}"</span>,                           <span style="color: #339966">// URL with parameters</span>
    <strong>new </strong>{ controller = <span style="color: #ff0000">"Home"</span>, action = <span style="color: #ff0000">"Index"</span>, id = <span style="color: #ff0000">""</span> }  <span style="color: #339966">// Parameter defaults</span>
);</code></pre>
</blockquote>
<p>Note that <code>MapRoute </code>is actually not part of the routing system; it&#8217;s an extension method added to <code>RouteCollection </code>by ASP.NET MVC. Calling <code>MapRoute </code>will add a single route to the <code>RouteCollection</code>. Most web applications will have only one <code>RouteCollection</code>, stored in <code>System.Web.Routing.RouteTable.Routes</code>. The most important thing that <code>MapRoute </code>does is to create and pass an <code>MvcRouteHandler </code>instance when adding the route to the <code>RouteCollection</code>. This ensures that when ASP.NET handles an incoming URI which matches this route, control will be passed to the MVC framework for handling the request.</p>
<p>The second argument to <code>MapRoute </code>is named "<code>url</code>", but it&#8217;s not really a complete URL. Instead, it is a template for a fragment of a URL containing <em>a portion of</em> the path component of a URI. I say "a portion of the path" because it omits the site root, which I&#8217;ve called "<code><code>/SiteRoot</code></code>" in the example above. The site root is often empty, but it doesn&#8217;t have to be. The URIs produced by the routing system include quite a bit more than the path, however. They also include the scheme/authority (in other words, the protocol and host) and, sometimes, a query.</p>
<p>There are a number of overloads to MapRoute. In addition to the values passed in this simple example, you can also pass constraints (which I&#8217;ll discuss in a moment) and namespaces. The namespaces argument is for MVC only (it&#8217;s not used by routing) and is useful when you want to put a Controller in a place where MVC wouldn&#8217;t otherwise find it.</p>
<p>A route can also contain <code>DataTokens</code>, which are not used by the routing system, but are passed to the route handler. <code>MapRoute </code>doesn&#8217;t have an overload which includes these as an argument, and I&#8217;m not going to discuss them in this post. ASP.NET MVC uses them only to store the <code>namespaces </code>argument, discussed above.</p>
<h2>Parsing a URI</h2>
<p>Let&#8217;s examine what happens when the routing system is asked to interpret a URI submitted by the user. Importantly, the RouteCollection is ordered. So the routing system will attempt to match the routes in the collection in the order you added them. The first matching route "wins" even if a later route is a "better" match. The incoming URI is compared with the url portion of the route. If it matches, the entire URI, including the query, is tokenized. If there are any constraints on the route, these are considered.</p>
<p><em>In practice, this means that if you have a lot of routes, then you are almost guaranteed to encounter a bug, sooner or later, where the wrong route is matched to an incoming URI. The only good way to prevent this that I know of is to write unit tests for your routes.</em> Unfortunately, the name of the route is not actually part of the route itself. It is stored in a private, internal dictionary in the RouteCollection. So there is no way to write a unit test which examines the name of the route returned.</p>
<p>Let&#8217;s use the sample URI and route from earlier in this post as an example. Out of the entire URI, <code>http://www.example.com:80/SiteRoot/</code><code>Controller/Action</code><code>?foo=A&amp;bar=B#anchor</code>, the routing system is only going to examine this bit when processing an incoming URI:</p>
<p><code>/</code><code>Controller/Action</code><code>?foo=A&amp;bar=B#anchor</code></p>
<p>Does this match the url portion of the route defined above? Recall that it is defined as:</p>
<pre><code><span><span style="color: #ff0000">"{controller}/{action}/{id}"
</span></span></code></pre>
<p>Yes, it matches, because "<code>Controller</code>" can be interpreted as the "<code>{controller}</code>" portion of the <code>url</code>, "<code>Action</code>" for the "<code>{action}</code>" part, and a default value exists for the "<code>{id}</code>" portions (empty string). Note that this means that having default values in a route makes that route much more likely to "match" an incoming URI. If there are defaults for every token in a URL pattern and there are no constraints, then that route will match every incoming URI. The route shown in this post is created by the MVC framework as a "catch all" route for a new application, which contains only that route. That is why it has defaults for all of its values and no constraints; it is intended to match every incoming URI. If, on the other hand, you write a special-purpose route intended only for one particular controller or action, and you provide default values for all of the tokens, then you need to implement constraints to prevent this route for matching other controllers or actions.</p>
<p>Because the url matches, we have five values, so far, to pass as the route data. "controller" will have the value Controller, and "action" will have the value "Action". "id" will have the default value. Also, from the query, "foo" will have the value "A", and "bar" will have the value "B". Now the routing system considers any constraints on the route, but in this case, there aren&#8217;t any. Therefore, this list of values is handed to the MvcRouteHandler which was created by MapRoute.</p>
<p><em>Importantly</em>, note that all of these values are strings. The routing system only deals with URIs, which are always strings. Now, your actions on your controllers can have arguments which are not strings, and the MVC framework will attempt to coerce the strings supplied by the routing system into whatever type is specified in the method signature. But that&#8217;s a feature of the MVC framework, not of the routing system. (Yes, the <code>Values</code> property returns type <code>object</code>, but, when matching an incoming URI, the segments are always added as strings.)</p>
<p>Not all URI patterns are as simple as the default route from the standard MVC application template. You can use delimiters other than /, for example. If you have hyphens, parentheses, etc. in your <code>url </code>template, these will be matched against the incoming URI to determine if the route is a match. The following route, for example, would not match the sample URI at the top of the post, even though it contains all of the necessary tokens and has no constraints:</p>
<blockquote>
<pre><code>routes.MapRoute(
    <span style="color: #ff0000">"Parenthesized"</span>,                                        <span style="color: #339966">// Route name</span>
    <span style="color: #ff0000">"{controller}({action})({id})"</span>,                         <span style="color: #339966">// URL with parameters</span>
    <strong>new </strong>{ id = <span style="color: #ff0000">""</span> }                    <span style="color: #339966">                     // Parameter defaults</span>
);</code></pre>
</blockquote>
<p>The incoming URI contains no parentheses, so this route can&#8217;t match, because the parentheses are needed to to delimit the values for <code>controller</code> and <code>action</code>, and there are no defaults for this values.</p>
<h2>Matching a Route With an Action</h2>
<p>After a route is matched to an incoming URI, and a list of route values is created, control goes to the <code>MvcRouteHandler</code>. Now the MVC framework can invoke the action on the controller specified by the "action" and "controller" route values. Note that there is nothing special about these names/values to the routing system; they&#8217;re just two more values in the list from the routing system&#8217;s point of view. But these two names, "action" and "controller" are very important to the MVC framework, for obvious reasons.</p>
<p><code>MvcRouteHandler </code>(indirectly) calls <code>MvcHandler.ProcessRequest</code>, which constructs the controller using the <code>ControllerFactory</code>, and then calls <code>Controller.Execute</code>, which, in turn, invokes the action using the <code>ControllerActionInvoker</code>. It is at this point that the values in the route are matched against the arguments for the action. In other words, tokenizing the URI and matching those values with action arguments are two entirely separate operations. The tokenizing is done by the routing system, and the matching route values with controller action arguments is done by the MVC framework.</p>
<p>In order to invoke the action, the MVC framework needs to look at the individual arguments to the action, and match them with route values. This is performed by the model binding system.</p>
<p>Note that the name of the argument does not have to correspond to a name in the route values if the model binding system can instantiate an instance of the type of the argument from the values which do exist. For example, if the type of the argument is FormCollection, then this argument can always be passed, no matter what names are present in the route values, and no matter what the name of the argument. The model binding system knows that it can always create a FormCollection by rolling up any values in the form in the incoming POST, if there are any. If there are not, it will simply return an empty FormCollection.</p>
<p>If the action takes an argument which cannot be instantiated based on the data in the route values, that is fine, so long as the argument is nullable. If the action requires a non-nullable argument which is not in the route values, or if the route values contain a value for an argument which cannot be bound into the type of that argument, the MVC framework will throw an exception. Otherwise, the action will be invoked.</p>
<h2>Creating a URI With RouteLink</h2>
<p>Creating an "<strong>a href=</strong>" tag with <code>Html.RouteLink</code> is trivial. The routing system looks up the route by name, and populates the URI with values from the <code>RouteCollection </code>you passed. Any values in the <code>RouteCollection </code>not included in the string in the <code>url </code>argument to <code>MapRoute </code>will be added to the resulting link as query string parameters. In my view, you should always prefer <code>RouteLink </code>over <code>ActionLink</code>, whenever there is any ambiguity as to which route will be returned.</p>
<p>Again, let&#8217;s consider an example, with the route defined in the MapRoute call earlier in this post:</p>
<blockquote>
<pre><code>&lt;%= Html.RouteLink(<span style="color: #ff0000">"Link text to display on page"</span>, <span style="color: #ff0000">"Default"</span>,
    <strong>new </strong><span style="color: #339966">RouteValueDictionary</span>(<strong>new </strong>{controller = <span style="color: #ff0000">"Foo"</span>, action = <span style="color: #ff0000">"Bar"</span>, foo = <span style="color: #ff0000">"A"</span>, bar = <span style="color: #ff0000">"B"</span> })) %&gt;</code></pre>
</blockquote>
<p>With this example, the order of the routes in the <code>RouteCollection</code>, the constraints, etc., are not needed to find the matching route, because we have specified ("<code>Default</code>") directly. Since there are no tokens called "foo" and "bar" in the <code>url</code> argument we passed to <code>MapRoute</code>, these will be appended to the generated URI as query string parameters. So we end up with the sample URI at the top of this post, less the anchor, provided that the site is configured to live in /SiteRoot.</p>
<h2>Creating a URI With ActionLink</h2>
<p><code>ActionLink </code>is more complicated, because the routing system must first <em>find </em>an appropriate route, and then use that route to generate the URI. In a way, the method of finding the route is similar to the method used when parsing a URI, insofar as the first matching route "wins." But in another way, it is very different, because there is no incoming URI to use as a pattern for matching the partial template passed as the <code>url</code> argument to <code>MapRoute</code>. The only thing that the <code>url</code> argument is used for in this scenario is determining which tokens must be included, either directly, or via defaults, in order for a route to match. Let&#8217;s re-examine the same scenario considered in the RouteLink section, above, only this time using <code>ActionLink</code>. The call looks like this:</p>
<blockquote>
<pre><code>&lt;%= Html.ActionLink(<span style="color: #ff0000">"Link text to display on page"</span>, <span style="color: #ff0000">"Bar"</span>, <span style="color: #ff0000">"Foo"</span>,
    <strong>new </strong><span style="color: #339966">RouteValueDictionary</span>(<strong>new </strong>{foo = <span style="color: #ff0000">"A"</span>, bar = <span style="color: #ff0000">"B"</span> })) %&gt;</code></pre>
</blockquote>
<p>Does this match the route defined at the top of this post? Yes it does, and here&#8217;s why: That route contains three tokens in its <code>url </code>argument. They are <code>controller</code>, <code>action</code>, and <code>id</code>. I have supplied values for two of these tokens in the call to <code>ActionLink</code>, namely <code>controller </code>and <code>action</code>, via the <code>controller </code>and <code>action </code>arguments in the overload of <code>ActionLink </code>I am using here. The remaining required token, <code>id</code>, is not supplied in the <code>ActionLink </code>call at all. However, there was a default for it (empty string) in the original call to <code>MapRoute</code>, so the route matches even without an explicit value for <code>id</code>. Because <code>foo </code>and <code>bar </code>are present in the <code>RouteValueDictionary</code>, but the <code>url </code>template in the route does not contain <code>{foo}</code> or <code>{bar}</code>, these will be added to the generated URI as query string parameters. Again, the generated URI will be the sample URI at the top of this post, less the anchor, provided that the site is configured to live in /SiteRoot.</p>
<h2>Conclusions</h2>
<p>I hope this long explanation has taken some of the mystery out of what routing does. Since there&#8217;s a lot of detail above, I&#8217;m going to summarize some of the information which is important for day-to-day work.</p>
<ul>
<li>Routing and the MVC framework are distinct features. MVC knows about Routing, but Routing does not know about MVC. Routing produces a list of values, but does not assign special meaning to them. MVC signs special meaning to the controller and action values.</li>
<li>Routes include information about a portion of the path in the URI and also the query, since any token not in the path is treated as part of the query.</li>
<li>The order of routes is very important, both for parsing incoming URIs and for generating URIs with ActionLink.</li>
<li>Default values in a route will cause the route to match more incoming URIs or sets of values in a <code>RouteValueDictionary</code>. Constraints in a route will cause the route to match fewer incoming URI this or sets of values in a <code>RouteValueDictionary</code>. If there are defaults for every token in a URL pattern and there are no constraints, then that route will match every incoming URI or sets of values in a <code>RouteValueDictionary</code>. For a "catch all" route like the one in the default MVC application, it is fine for all of the tokens to have default values in for there to be no constraints. If you write a special-purpose route for a particular controller or action, however, then you should probably use constraints to prevent it from ever matching any other controller or action.</li>
<li>If you have more than one route, then you simply <em>must </em>write unit tests to ensure that the correct route is selected for all incoming URIs or values used in your calls to ActionLink.</li>
</ul>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38085&amp;akst_action=share-this" onclick="akst_share('38085', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F18%2F38085%2F', 'ASP.NET+Routing+and+ASP.NET+MVC'); return false;" title="Post to del.icio.us, etc." id="akst_link_38085" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ASP.NET%20Routing%20and%20ASP.NET%20MVC&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F18%2F38085%2F" id="akst_email_38085" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Not-So-Secret Sale</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/17/38109/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/17/38109/#comments</comments>
    <pubDate>Tue, 17 Mar 2009 11:02:09 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38109</guid>
    <description><![CDATA[Upscene Productions is offering their Database Workbench Pro product for 75% off, through 28 March 2009 only. They call this the "Super Secret Sale," but since Martijn asked me to post it here, I&#8217;m not sure how much of a secret it is. Anyway, 75% off is about as cheap as you&#8217;ll ever find it, [...]]]></description>
      <content:encoded><![CDATA[<p>Upscene Productions is <a href="http://www.upscene.com/dbw_secretsupersale.php">offering their Database Workbench Pro product for 75% off</a>, through 28 March 2009 only. They call this the "Super Secret Sale," but since Martijn asked me to post it here, I&#8217;m not sure how much of a secret it is. Anyway, 75% off is about as cheap as you&#8217;ll ever find it, so if you&#8217;ve been considering buying the tool, now is a good time.</p>
<p><a href="http://www.upscene.com/products.dbw.index.php">Database Workbench</a> supports InterBase and many other DB servers. You can buy the module for one (or more) DB server only if you don&#8217;t need all of them.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38109&amp;akst_action=share-this" onclick="akst_share('38109', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F17%2F38109%2F', 'A+Not-So-Secret+Sale'); return false;" title="Post to del.icio.us, etc." id="akst_link_38109" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Not-So-Secret%20Sale&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F17%2F38109%2F" id="akst_email_38109" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>SQL Performance Tuning Book Includes InterBase</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/16/38097/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/16/38097/#comments</comments>
    <pubDate>Mon, 16 Mar 2009 19:21:22 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38097</guid>
    <description><![CDATA[SQL Performance Tuning, by Peter Gulutzan and Trudy Pelzer, "is a guide for users and programmers who want to improve SQL performance no matter what brand of SQL they use. &#8230; All the ideas have been tested against the eight leading DBMS applications."
I haven&#8217;t read this book, but someone in the newsgroups mentioned that it [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.pearsoned.co.uk/Bookshop/detail.asp?item=302416">SQL Performance Tuning, by Peter Gulutzan and Trudy Pelzer</a>, "is a guide for users and programmers who want to improve SQL performance no matter what brand of SQL they use. &#8230; All the ideas have been tested against the eight leading DBMS applications."</p>
<p>I haven&#8217;t read this book, but <a href="https://forums.codegear.com/thread.jspa?threadID=13638&amp;tstart=0#91911">someone in the newsgroups mentioned that it included InterBase</a>. He writes:</p>
<p style="padding-left: 30px">"Note that they tested on IB6 — but I have still found most of their advice to be valid."</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38097&amp;akst_action=share-this" onclick="akst_share('38097', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F16%2F38097%2F', 'SQL+Performance+Tuning+Book+Includes+InterBase'); return false;" title="Post to del.icio.us, etc." id="akst_link_38097" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=SQL%20Performance%20Tuning%20Book%20Includes%20InterBase&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F16%2F38097%2F" id="akst_email_38097" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>A Functional View of A Web Server</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/05/38072/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/05/38072/#comments</comments>
    <pubDate>Thu, 05 Mar 2009 14:31:35 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38072</guid>
    <description><![CDATA[A few days ago, I opined that, "Web applications, as a class, are extremely easy to debug." I&#8217;m going to further explain why I think that is true by introducing a useful abstraction which you can employ when you are debugging a web application which doesn&#8217;t seem to do what is is intended to do.
When [...]]]></description>
      <content:encoded><![CDATA[<p>A few days ago, I opined that, "<a title="The Web Is Just Text" href="http://blogs.teamb.com/craigstuntz/2009/02/16/38024/">Web applications, as a class, are extremely easy to debug.</a>" I&#8217;m going to further explain why I think that is true by introducing a useful abstraction which you can employ when you are debugging a web application which doesn&#8217;t seem to do what is is intended to do.</p>
<p>When a web application misbehaves, one of the first things you&#8217;ll need to do is determine if the problem is in the browser/client (e.g., buggy JavaScript, attempting to use CSS on IE 6, etc.) or in the server application (e.g., returns incorrect HTML, inserts wrong data into database, etc.). In order to make this distinction, it is helpful to use a very simple conception of what a web application does. HTTP is a stateless protocol. Therefore, a web server is expected to always return the same results in response to a certain request, without regard to what has happened beforehand. So we can consider the server as a single function:</p>
<div id="attachment_38073" class="wp-caption alignnone" style="width: 510px"><a href="/files/2009/03/web-server-function_1054.png"><img src="/files/2009/03/web-server-function_1054.png" alt="(Browser request, state) -&gt; web server -&gt; result (usually HTML)" width="500" height="194" /></a><p class="wp-caption-text"> </p></div>
<p>The illustration above may appear a bit strange, because of the close proximity of the browser and the database server. In reality, we know that the database server is likely closer to the web server than to the browser. But remember, I am attempting to treat the web server as a pure function here (I&#8217;ll explain why in a minute). The state of the database, if there is one, will certainly affect the page returned by the web server. Therefore, it is an input to the function. Similarly, authentication, which can also change the page returned by the web application is most often stored in a cookie. So cookies are also inputs to the server function.</p>
<p>Using this abstraction, it is now very easy to diagnose where the bug exists, by looking at the inputs to the function and its result:</p>
<ul>
<li>If the inputs are correct and the result is wrong, then the bug is in the server. But remember that "result" means the HTML returned by the server, not the manner in which the browser renders it. It is possible for correct HTML to be rendered incorrectly, especially if JavaScript or <a title="IE is teh 3v1l" href="http://weblog.jamisbuck.org/2005/6/3/ie-is-teh-3v1l">IE 6</a> are involved.</li>
<li>If the inputs are incorrect, then the bug is obvious. But remember, inputs can include things like form data which, for some reason, people don&#8217;t always tend to examine.</li>
<li>If the inputs and the result are both correct, but the page still looks wrong in the browser, then the bug is in the browser/client side.</li>
</ul>
<p>The only circumstance in which this abstraction doesn&#8217;t really work is when you&#8217;re maintaining state on the client. An example would be when using frames. If you click a link which targets a frame, the result that you see in the browser will be different depending upon what you have done before, because you might have other pages open in other frames. This is an example of why I think that frames are not a good architectural fit with the rest of the web.</p>
<p>Once you&#8217;ve determined eactly where the bug lives, you are well on your way to fixing it. You can also describe the bug with more precision. For example, you will say things like "the server returns incorrect HTML (incorrect style on the div with ID &#8216;foo&#8217;) when&#8230;" instead of "the panel is on the wrong place in the page when&#8230;".</p>
<h3>Colophon</h3>
<p>It&#8217;s not really relevant to the rest of the post, but here is how I made the illustration above. I decided the post would be easier to understand if I included a diagram of the function. So I followed my standard process for using Microsoft Visio, which is something along the lines of the following:</p>
<ol>
<li>Decide that I need a very simple block diagram, and remember that this is something which Visio is supposed to be good at.</li>
<li>Attempt to use Visio to produce the diagram.</li>
<li>"WTF, I&#8217;m not allowed to resize this? I thought that Visio was supposed to be for <em>simple </em>drawings."</li>
<li>Decide, "Wow, I&#8217;d forgotten how much I really despise Visio."</li>
<li>Produce diagram in some other piece of software.</li>
<li>Repeat, 6 months later. Some day I&#8217;ll learn.</li>
</ol>
<p>I ended up using <a href="http://www.inkscape.org/">Inkscape</a>, which has more than a few rough edges, but which was good enough to produce a simple diagram, which is more than I can personally say for Visio. The drawing includes an MPLed globe image, so I&#8217;m releasing the whole drawing under the terms of the MPL.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38072&amp;akst_action=share-this" onclick="akst_share('38072', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F05%2F38072%2F', 'A+Functional+View+of+A+Web+Server'); return false;" title="Post to del.icio.us, etc." id="akst_link_38072" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=A%20Functional%20View%20of%20A%20Web%20Server&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F05%2F38072%2F" id="akst_email_38072" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Columbus Architecture Group Lightning Talks</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/03/02/38063/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/03/02/38063/#comments</comments>
    <pubDate>Mon, 02 Mar 2009 15:58:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38063</guid>
    <description><![CDATA[The Columbus Architecture Group, a special interest group for software architects, is hosting "lightning talks" (a series of short, 10-20 minute presentations) tonight, at 6:00 p.m. in the Quick Solutions offices. I will be presenting a talk on "The Structure and Interpretation of URIs." See the list of other topics at the link.
Share This &#124; [...]]]></description>
      <content:encoded><![CDATA[<p><a href="http://www.colarc.org/2009/02/march-lightening-talks.html">The Columbus Architecture Group, a special interest group for software architects, is hosting "lightning talks"</a> (a series of short, 10-20 minute presentations) tonight, at 6:00 p.m. in the <a href="http://www.quicksolutions.com">Quick Solutions offices</a>. I will be presenting a talk on "The Structure and Interpretation of URIs." See the list of other topics at the link.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38063&amp;akst_action=share-this" onclick="akst_share('38063', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F02%2F38063%2F', 'Columbus+Architecture+Group+Lightning+Talks'); return false;" title="Post to del.icio.us, etc." id="akst_link_38063" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Columbus%20Architecture%20Group%20Lightning%20Talks&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F03%2F02%2F38063%2F" id="akst_email_38063" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Sampling Profiler</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/25/38058/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/25/38058/#comments</comments>
    <pubDate>Wed, 25 Feb 2009 14:26:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38058</guid>
    <description><![CDATA[Eric Grange&#8217;s free, sampling profiler for Delphi finally has a site to call its home.
]]></description>
      <content:encoded><![CDATA[<p><a href="http://delphitools.info/">Eric Grange&#8217;s free, sampling profiler</a> for Delphi finally has a site to call its home.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38058&amp;akst_action=share-this" onclick="akst_share('38058', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F25%2F38058%2F', 'Sampling+Profiler'); return false;" title="Post to del.icio.us, etc." id="akst_link_38058" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Sampling%20Profiler&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F25%2F38058%2F" id="akst_email_38058" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>All Access</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/20/38045/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/20/38045/#comments</comments>
    <pubDate>Fri, 20 Feb 2009 20:01:08 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[InterBase]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38045</guid>
    <description><![CDATA[Embarcadero&#8217;s DavidI and Mike Rozlog stopped by the Vertex Systems office on Wednesday to chat with us about Embarcadero&#8217;s plans for the near future and David&#8217;s personal developer wish list.
They told us about the All Access product, which had been officially released that day. One of the most interesting things about this product is that [...]]]></description>
      <content:encoded><![CDATA[<p>Embarcadero&#8217;s <a href="http://blogs.codegear.com/davidi/">DavidI</a> and <a href="http://blogs.embarcadero.com/michaelrozlog/">Mike Rozlog</a> stopped by the <a href="http://www.vertexsystems.com/">Vertex Systems</a> office on Wednesday to chat with us about Embarcadero&#8217;s plans for the near future and David&#8217;s personal developer wish list.</p>
<p>They told us about the <a href="http://embarcadero.com/products/all_access/">All Access</a> product, which had been officially released that day. One of the most interesting things about this product is that it is installation-free, or so Embarcadero claims. It uses a virtualized registry, etc., so that you can just start the application directly. I&#8217;m thinking that this might be useful even outside of the context of All Access. Especially for something like a build machine, where you might want to run it in various different configurations. Sort of like a "lite" VM. It will be interesting to see if Embarcadero uses this technology outside of All Access.</p>
<p>One thing I wonder about right now: Perhaps the biggest differentiator between Delphi Enterprise and Delphi Architect is that with Architect you get Embarcadero <a href="http://embarcadero.com/products/er_studio/index.php">ER/Studio</a>. So with the way the SKUs are differentiated right now, All Access is sort of an alternative to Architect. That&#8217;s how it seems to me, anyway. I suspect that we will see a different feature mix in Architect in the future.</p>
<p>David expressed a lot of relief at not being part of Borland anymore. He said that since Embarcadero is private, they can talk about upcoming features more freely than when they were part of a publicly held corporation.</p>
<p>David also talked about how Delphi developers who do database work could really benefit from the Embarcadero database tools. He wants to bring the integration much closer. For example, he wants you to be able to step into the Rapid SQL <a href="http://embarcadero.com/products/debugger/">stored procedure debugger</a> directly when debugging through a Delphi application which called a stored procedure in the database. Embarcadero has profilers for Java applications and for database servers; you can see the potential for interaction there, too.</p>
<p>We are looking for a good solution for doing heterogeneous, bidirectional replication between InterBase and SQL Server. We have a working solution already using a SQL Server job and linked servers, but I would prefer a solution that we do not have to develop and maintain. I am aware of <a href="http://www.microtec.fr/copycat/ct/">CopyTiger</a>, which claims to support both, but doesn&#8217;t really seem flexible enough to do what we need. There are a lot of replicators which doesn&#8217;t explicitly support InterBase, that support JDBC or ODBC connections, and they could possibly be a solution. David suggested that Embarcadero&#8217;s <a href="http://embarcadero.com/products/change_manager/">Change Manager</a> product would be a potential solution for us, so we&#8217;re going to look into that.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38045&amp;akst_action=share-this" onclick="akst_share('38045', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F20%2F38045%2F', 'All+Access'); return false;" title="Post to del.icio.us, etc." id="akst_link_38045" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=All%20Access&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F20%2F38045%2F" id="akst_email_38045" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery 1.3.1 Selector Bug and Workaround</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/17/38038/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/17/38038/#comments</comments>
    <pubDate>Tue, 17 Feb 2009 11:36:56 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38038</guid>
    <description><![CDATA[In jQuery 1.2.6, if you wanted to select all inputs with empty values, you could do this:
var emptyInput = $("form input[value='']");
That&#8217;s a little hard to read, so note that the quotes around the entire selector are double quotes, but the quotes inside the square brackets are two single quotes. This says, "Give me any input [...]]]></description>
      <content:encoded><![CDATA[<p>In jQuery 1.2.6, if you wanted to select all inputs with empty values, you could do this:</p>
<blockquote><p><code><strong>var </strong>emptyInput = $("form input[value='']");</code></p></blockquote>
<p>That&#8217;s a little hard to read, so note that the quotes around the entire selector are double quotes, but the quotes inside the square brackets are two single quotes. This says, "Give me any input where the value is equal to empty string."</p>
<p><a title="1.3.1 selector bug - $('input[value=&quot;&quot;]')" href="http://dev.jquery.com/ticket/3990">This is broken in jQuery 1.3.1</a>. Try it, and you will see (if you have a debugger attached):</p>
<blockquote><p>Syntax error, unrecognized expression: value=""]</p></blockquote>
<p><a title="Changeset 6181" href="http://dev.jquery.com/changeset/6181">A fix for the bug has been checked in</a>, so you can get a corrected version in the nightly build. If you prefer to stick with 1.3.1, I&#8217;ve found a workaround; do this instead:</p>
<blockquote><p><code><strong>var </strong>emptyInput = $("form input:not([value])");</code></p></blockquote>
<p>This works because empty string is implicitly converted to false in JavaScript.</p>
<p><strong>Update: </strong>The bug is fixed in jQuery 1.3.2.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38038&amp;akst_action=share-this" onclick="akst_share('38038', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F17%2F38038%2F', 'jQuery+1.3.1+Selector+Bug+and+Workaround'); return false;" title="Post to del.icio.us, etc." id="akst_link_38038" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%201.3.1%20Selector%20Bug%20and%20Workaround&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F17%2F38038%2F" id="akst_email_38038" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Web Is Just Text</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/16/38024/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/16/38024/#comments</comments>
    <pubDate>Mon, 16 Feb 2009 14:18:26 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38024</guid>
    <description><![CDATA[In the beginning (around 1990 or so), the World Wide Web was composed of three parts:

HTML, a markup language for displaying rich documents
HTTP, a stateless protocol for communicating with a web server
The URI, a short, standardized reference to a network resource

Almost 20 years later, very little has changed, especially from the point of view of [...]]]></description>
      <content:encoded><![CDATA[<p>In the beginning (around 1990 or so), the World Wide Web was composed of three parts:</p>
<ul>
<li><a href="http://www.w3.org/TR/1999/REC-html401-19991224/">HTML</a>, a markup language for displaying rich documents</li>
<li><a href="http://tools.ietf.org/html/rfc2616">HTTP</a>, a stateless protocol for communicating with a web server</li>
<li>The <a href="http://tools.ietf.org/html/rfc3986">URI</a>, a short, standardized reference to a network resource</li>
</ul>
<p>Almost 20 years later, very little has changed, especially from the point of view of the server. To the list above, we have added client-side stuff like JavaScript and CSS, and HTML is now at version 4. But HTTP and the URI are close to unchanged.</p>
<p>And <em>all three</em> of the items in the list above <em>are just text</em>. Not just any text, mind you, but text which is formatted in such a way as to be mostly easy for humans to read.</p>
<p><strong>This means that what web servers do is very simple.</strong> They accept text over a text-based protocol and return more text.</p>
<p>Despite this, people occasionally seem to find web servers confusing, in part because we like to lie about what they do. For example, you might see a URI which looks like this:</p>
<blockquote><p><code>http://www.example.com/foo.php</code></p></blockquote>
<p><strong>This is a lie.</strong> If you point a web browser at this URI, you will almost certainly not receive a PHP source file; instead, you will probably get HTML. That the HTML was generated with PHP source code is an implementation detail unsuitable for inclusion in a Uniform <strong>Resource </strong>Identifier.</p>
<p>Some people might think I&#8217;m being pedantic here. How many end users actually care what the extension in the URI is? These are probably the same people who post questions on Stack Overflow wondering why their web application doesn&#8217;t work, but not including in the question <em>the only things that the server really cares about</em>, which you can find in the list at the beginning of this post. It doesn&#8217;t matter if you generated your HTML using aspx, rhtml, or PHP. It&#8217;s still just plain HTML to the browser. When you submit a form, you&#8217;re submitting name/value pairs of strings, not "integers" and "dates" and "classes."</p>
<p>That&#8217;s why this matters to a programmer: <strong>Web applications, as a class, are <em>extremely </em>easy to debug.</strong> Tools like <a href="http://getfirebug.com/">Firebug</a> and <a href="http://www.fiddlertool.com/">Fiddler</a> allow you to see the text that is exchanged between the browser and the server, and even pretty it up a little to make it more readable than it already is. But already built-in to your web browser is the single most important tool that you need for debugging a web application; namely, the "View Source" command. Chances are very good that if you look at the HTML, the HTTP, and the URI, you can solve whatever issue you&#8217;re having with your web application. But if you can&#8217;t, including whichever of these three is relevant to the problem at hand will dramatically increase the chances of getting a solution when you ask someone else to help you out.</p>
<p>Perhaps it&#8217;s the fact that we&#8217;re used to debugging within an IDE which causes people to look at, for example, aspx source code instead of HTML when a web page doesn&#8217;t render the way we&#8217;d like, or to debug through model binders instead of looking at a form submission when the input to a controller action is not what we expect. But remember, the browser doesn&#8217;t see your aspx or PHP. The browser just sees the HTML you generate.</p>
<p>Perhaps another reason why this tends to confuse people is that certain web frameworks, such as ASP.NET, introduce fictions such as "event handlers" and "postbacks." <em>No such concepts exist within HTTP.</em> Instead, they are (extraordinarily leaky) abstractions built on top of HTTP within a certain framework. But under the hood, there is still just HTTP. If you want to understand the communication between your web application and a browser, look at the HTTP and the HTML.</p>
<p>I&#8217;m going to close this post with a recommendation: If you&#8217;ve never <a href="http://tonycode.com/wiki/index.php?title=Making_HTTP_requests_via_telnet">visited a web site via telnet</a>, go do it right now. It only takes a second, and <a href="http://www.dgate.org/~brg/bvtelnet80/">you&#8217;ll learn a lot in the process</a>. This is an easy way to understand at a very fundamental level how web browsers and web servers talk to each other. If you need to debug your web application at a client site and can&#8217;t install Fiddler, you can probably use Telnet instead.</p>
<p>This is the first article in a series on <a href="http://blogs.teamb.com/craigstuntz/tag/the-dynamic-web/">the dynamic web.</a></p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38024&amp;akst_action=share-this" onclick="akst_share('38024', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F16%2F38024%2F', 'The+Web+Is+Just+Text'); return false;" title="Post to del.icio.us, etc." id="akst_link_38024" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Web%20Is%20Just%20Text&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F16%2F38024%2F" id="akst_email_38024" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>jQuery and ASP.NET MVC Model Binding to a List</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/11/38013/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/11/38013/#comments</comments>
    <pubDate>Wed, 11 Feb 2009 20:08:33 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38013</guid>
    <description><![CDATA[In ASP.NET MVC, when you want to submit a page with many instances of a certain type (e.g., a form with a list of phone numbers), the framework will recognize the form elements as a list if you use a specific format for the name attribute of the inputs. This allows you to have an [...]]]></description>
      <content:encoded><![CDATA[<p>In ASP.NET MVC, when you want to submit a page with many instances of a certain type (e.g., a form with a list of phone numbers), the framework will recognize the form elements as a list if you <a title=" ASP.NET MVC RC1 - Binding a List" href="http://www.distribucon.com/blog/ASPNETMVCRC1BindingAList.aspx">use a specific format for the name attribute of the inputs</a>. This allows you to have an action <a title="Model Binding To A List" href="http://haacked.com/archive/0001/01/01/model-binding-to-a-list.aspx">like this</a>:</p>
<blockquote>
<pre><code><strong>public </strong>ActionResult UpdateInts(IList&lt;<strong>int</strong>&gt; ints) {
</code></pre>
</blockquote>
<p>The MVC framework, in this case, will look at all the inputs on your form, figure out which inputs correspond to which records on the form, find each record individually, and pass the whole list to your action as an IList&lt;T&gt;. Pretty convenient, that.</p>
<p>Note that the format for the name element requires square brackets and a period.<code> </code></p>
<blockquote>
<pre><code><span class="kwrd">&lt;<strong>input </strong>type="text" name="products[0].Name" value="Beer" /&gt;</span>
</code></pre>
</blockquote>
<p>There is no way around this required formatting; it is hard-coded into the framework source code. (See DefaultModelBinder.cs.)</p>
<p>Unfortunately, these are special characters in jQuery selectors. As a result, some plug-ins can become unhappy when you use them in an input name. For example, the <a href="http://plugins.jquery.com/project/ClockPick">ClockPick plugin</a> has <a href="http://www.oakcitygraphics.com/jquery/clockpick/trunk/ClockPick.cfm">an option</a> which is useful when you want an image that the user can click on in order to pop up the clock picker instead of clicking on the input itself:</p>
<blockquote>
<pre><code><span class="kwrd">$(".clockpick").clockpick({
    valuefield : 'myfieldname'
});</span></code></pre>
</blockquote>
<p>If the name attribute of your input happens to be <code>myfieldname</code>, this works fine. If, on the other hand, it is <code><span class="kwrd">products[0].Name</span></code>, it doesn&#8217;t work at all.</p>
<p>The solution is to include an extra set of quotes around the name with the brackets and the dot:</p>
<blockquote>
<pre><code><span class="kwrd">$(".clockpick").clockpick({
    valuefield : "'</span></code><code><span class="kwrd">products[0].Name</span></code><code><span class="kwrd">'"
});
</span></code></pre>
</blockquote>
<p>With only one set of quotes, we just have a string containing <code>products[0].Name</code>. With two sets of quotes, the string contains the same thing, except surrounded by quotes. This causes jQuery to not treat the square brackets and the dots as special characters. As <a title="API/1.3/Selectors" href="http://docs.jquery.com/Selectors">the jQuery documentation notes</a>:</p>
<blockquote><p>Quotes are optional in most cases, but should be used to avoid conflicts when the value contains characters like "]".</p></blockquote>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38013&amp;akst_action=share-this" onclick="akst_share('38013', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F11%2F38013%2F', 'jQuery+and+ASP.NET+MVC+Model+Binding+to+a+List'); return false;" title="Post to del.icio.us, etc." id="akst_link_38013" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=jQuery%20and%20ASP.NET%20MVC%20Model%20Binding%20to%20a%20List&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F11%2F38013%2F" id="akst_email_38013" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Generics, Commas, and Semicolons</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/09/38000/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/09/38000/#comments</comments>
    <pubDate>Mon, 09 Feb 2009 18:19:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Delphi]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=38000</guid>
    <description><![CDATA[In Delphi 2009, you declare a generic type with multiple type parameters by separating the type parameters with a semicolon. If the type parameters have a constraint, you separate the constraint using a colon. Like this:

type
  TFoo&#60;TypeParam1; TypeParam2: ISomething&#62; = class

This means that TypeParam2 must support ISomething. In C#, you would use where instead [...]]]></description>
      <content:encoded><![CDATA[<p>In Delphi 2009, you <em>declare </em>a generic type with multiple type parameters by separating the type parameters with a semicolon. If the type parameters have a constraint, you separate the constraint using a colon. Like this:</p>
<blockquote>
<pre><code><strong>type</strong>
  TFoo&lt;TypeParam1; TypeParam2: ISomething&gt; = <strong>class</strong></code></pre>
</blockquote>
<p>This means that TypeParam2 must support ISomething. In C#, you would use <a title="Constraints on Type Parameters (C# Programming Guide)" href="http://msdn.microsoft.com/en-us/library/d5x73970(VS.80).aspx"><code>where</code></a> instead of the colon syntax.</p>
<p>To use (as opposed to declare) a generic type, however, you separate the type parameters with commas, like this:</p>
<blockquote>
<pre><code>  Foo := TFoo&lt;integer, TBar&gt;.Create;
</code></pre>
</blockquote>
<p>Does that seem a little odd? It might to a C# programmer, I guess. But it should look very familiar to a Delphi programmer, because it exactly mirrors the syntax for procedure arguments:</p>
<blockquote>
<pre><code>  <em>// declare:</em>
  <strong>procedure </strong>Foo(ArgA: integer; ArgB: boolean);
  <em>// invoke:</em>
  Foo(A, B);
</code></pre>
</blockquote>
<p>Indeed, the only reason this is really worth mentioning at all is that if you forget and you use a comma instead of a semicolon when declaring a list of type parameters in a generic type declaration, the message you get from the compiler is not especially helpful.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=38000&amp;akst_action=share-this" onclick="akst_share('38000', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F09%2F38000%2F', 'Generics%2C+Commas%2C+and+Semicolons'); return false;" title="Post to del.icio.us, etc." id="akst_link_38000" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Generics%2C%20Commas%2C%20and%20Semicolons&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F09%2F38000%2F" id="akst_email_38000" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>The Hidden Dangers of TRadioButton.TabStop</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/02/02/37987/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/02/02/37987/#comments</comments>
    <pubDate>Mon, 02 Feb 2009 20:12:28 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37987</guid>
    <description><![CDATA[TRadioButton has a TabStop property. It looks harmless enough. Why not set it? You&#8217;d like the user to be able to set radio button controls with the keyboard, right?
Trust me, just leave that little bastard alone.
To understand why, we should review the Windows standards for interacting with radio buttons using the keyboard. If you drop [...]]]></description>
      <content:encoded><![CDATA[<p>TRadioButton has a TabStop property. It looks harmless enough. Why not set it? You&#8217;d like the user to be able to set radio button controls with the keyboard, right?</p>
<p>Trust me, just leave that little bastard alone.</p>
<p>To understand why, we should review the Windows standards for interacting with radio buttons using the keyboard. If you drop several TRadioButtons onto a group box, then these buttons are treated as a group; although they aren&#8217;t quite the same thing as a TRadioGroup, they behave similarly. Namely, if you tab into the group box, then the checked radio button will receive input focus. If you press tab again, you will tab out of the group box. When the checked radio button has focus, pressing the arrow keys will check a different radio button in the group (and un-check all other radio buttons in the group box).</p>
<p>The VCL does not rely on Windows for this behavior; instead, it is implemented in the VCL source code, and you can trace through it.</p>
<p>The reason that this is on my mind is because of a curious bug report I received the other day. A tester reported that tabbing into a radio group on a certain form caused the selection to change (in other words, a different radio button was checked simply by tabbing into the group box). Based upon the explanation above, you can probably see where this is headed, but it took me a long time to figure out. The behavior was easy to reproduce, and I could even see a CN_COMMAND message of BN_CLICKED in the debugger, but it was near the top of the call stack, and I could not figure out where it was coming from.</p>
<p>It seems that if you tab to this particular radio button, and only this particular radio button, and only when you first enter the form, <em>Windows </em>will send BN_CLICKED. But why was I able to tab to a non-selected radio button at all? Shouldn&#8217;t focus go to the selected button?</p>
<p>No, not really. Again, Windows doesn&#8217;t choose which control is focused when you press tab; the Delphi VCL does. Glossing over a few details, it essentially looks for the next enabled control where TabStop is true. When you click a radio button, in addition to un-checking all of the other radio buttons in the group, the VCL sets their TabStop properties to False.</p>
<p><em>But only if they weren&#8217;t checked in the first place. </em>If a radio button is not already checked, then its TabStop property will not be set false when another radio button in the radio group has its Checked property set true.</p>
<p>So here is what actually happened:</p>
<ol>
<li>A few months ago, a well-meaning developer had done some tab order maintenance on the form in question. He changed the TabStop and TabIndex properties of a number of controls. The changes looked quite innocuous, and even passed code review.</li>
<li>Unfortunately, he had set TabStop true on a TRadioButton which was not Checked.</li>
<li>Some code in the form configured the radio group by setting the Checked property of a different radio button True. This caused the Checked and TabStop properties of the other radio buttons in the group to be set False, <em>but only if their Checked properties were not true to begin with.</em></li>
<li>Now the tester tabbed into the group box. The first radio button in the tab order was not checked, so a BN_CLICKED message is sent. The tester is surprised that the "wrong" radio button is focused, and, worse, it is checked, as well.</li>
</ol>
<p>The moral of the story? Just don&#8217;t touch the TRadioButton.TabStop property. The VCL is going to manipulate it in code. Leave it at its default value. If you want to change whether or not the user can tab into a group of radio buttons on a TGroupBox, then change the property of the container, instead.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37987&amp;akst_action=share-this" onclick="akst_share('37987', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F02%2F37987%2F', 'The+Hidden+Dangers+of+TRadioButton.TabStop'); return false;" title="Post to del.icio.us, etc." id="akst_link_37987" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=The%20Hidden%20Dangers%20of%20TRadioButton.TabStop&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F02%2F02%2F37987%2F" id="akst_email_37987" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>Data Structures for Time Records</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/29/37964/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/29/37964/#comments</comments>
    <pubDate>Thu, 29 Jan 2009 14:17:10 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[General Software Development]]></category>

		<category><![CDATA[InterBase]]></category>

		<category><![CDATA[Uncategorized]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37964</guid>
    <description><![CDATA[Over the years, I&#8217;ve had a number of occasions to need to store information about when somebody worked on a certain job. Sometimes people will want to store the date the work was done and the number of hours the employee worked, where as other people will need to store the start time and the [...]]]></description>
      <content:encoded><![CDATA[<p>Over the years, I&#8217;ve had a number of occasions to need to store information about when somebody worked on a certain job. Sometimes people will want to store the date the work was done and the number of hours the employee worked, where as other people will need to store the start time and the stop time (in other words, when the employee "punched in," and when the employee "punched out"). Often, the same customer will need to use both methods of recording time, depending upon the nature of the work recorded.</p>
<h2>A first try</h2>
<p>So here is a naïve attempt at creating metadata for this sort of data. I&#8217;m going to demonstrate this as a database table, but the issues involved are nearly identical when you create similar structures in code.</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIME</strong>,
  StopTime <strong>TIME</strong>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>This might look OK at first glance, <em>but it turns out to be fairly badly broken</em>. Before I discuss why, I should clarify the data types involved. <strong></strong></p>
<h2>What isn&#8217;t broken</h2>
<p>One thing you might notice when looking at this metadata is that I&#8217;ve made most of the columns nullable. In my experience, it is very important to allow users to save work in progress, and to only do validations (such as requiring that the Person is filled in) when you actually try to do something important that the time record, such as submit it for payroll. For example, an employee could begin a time record when they "punch in" at the beginning of a shift, and finish the time record when they "punch out" at the end of a shift.</p>
<p><strong>DATE </strong>and <strong>TIME </strong>in this DDL refer to the SQL Standard data types which contain, respectively, a date and a time only. The SQL Standard data type for a date and time in a single column is <strong>TIMESTAMP</strong>. Not all databases (or programming languages/environments) support such types. In many cases, you will have to do with only <strong>TIMESTAMP</strong>, or its equivalent, such as TDateTime in Delphi.</p>
<p>Note that TotalHours is <strong>NUMERIC</strong>, not <strong>TIME</strong>. It is important not to confuse a time span with a time of day; they are different units. In .NET, there is a <a href="http://msdn.microsoft.com/en-us/library/system.timespan.aspx">TimeSpan type</a> which is appropriate for this.</p>
<h2>Problems with the naïve approach</h2>
<p>Presuming that the user has filled in all of the required information for a time record, what would we expect to see in a typical row?</p>
<p>If the user is recording only the date and the number of hours worked, it seems pretty obvious: both the WorkDate and the TotalHours fields will be non-NULL, and the StartTime and StopTime columns will be NULL.</p>
<p>What if the user needs to record the start and stop times? Well, the WorkDate, StartTime and StopTime fields almost be non-NULL. But what about TotalHours? We could fill that in, but wouldn&#8217;t it be redundant with the information in StartTime and StopTime? Or, worse, could we even be sure that all three fields are kept "in sync?" So we might be tempted to leave that NULL, but then, what if we want to do a SUM in SQL? By filling in TotalHours, we can compute an employee&#8217;s total work time, even if some of the records are filled in with start times and stop times, but others were filled in with only the total hours worked.</p>
<table border="1">
<thead>
<th>Id</th>
<th>PersonId</th>
<th>WorkDate</th>
<th>StartTime</th>
<th>StopTime</th>
<th>TotalHours</th>
</thead>
<tbody>
<tr>
<td>0</td>
<td>100</td>
<td>2009-01-29</td>
<td>1:00 PM</td>
<td>1:30 PM</td>
<td>0.5</td>
</tr>
<tr>
<td>1</td>
<td>101</td>
<td>2009-01-29</td>
<td><em>NULL</em></td>
<td><em>NULL</em></td>
<td>1.5</td>
</tr>
</tbody>
</table>
<p>To compute the total hours on a record that has start and stop times, we might be tempted to subtract the start time from the stop time. But that doesn&#8217;t work. An employee could work a shift from 8 PM to 2 AM, yielding a negative result for this calculation.</p>
<p>We could make a rule that we add a day to the stop time before subtracting if it is less than the start time, but this presumes that the employee&#8217;s shift was less than 24 hours. Greater than 24 hour shifts may be uncommon, but they do happen; I once worked a 31 hour shift, fresh out of college.</p>
<p>What this means is that <em>recording only the start and stop times without the start and stop <strong>dates </strong>does not give us sufficient information to compute the total hours worked in all cases, and makes it more difficult in many cases</em>.</p>
<h2>Some useful redundancy</h2>
<p>Here&#8217;s another way to store this data. This is what I generally do. But I&#8217;ll forgive you if you&#8217;re skeptical when you see it. I&#8217;ll discuss some alternatives later.</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIMESTAMP</strong>,
  StopTime </code><code><strong>TIMESTAMP</strong></code><code>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>First, it is no longer a problem to compute TotalHours from the StopTime and StartTime, if they&#8217;re filled in. StopTime minus StartTime will always equal the correct total hours worked, when they are non-NULL. Also, it is no longer a problem to record a greater than 24 hour shift.</p>
<p>But isn&#8217;t there some redundancy here? WorkDate is always going to equal the date portion of StartTime, when StartTime is non-NULL. Somebody once suggested to me that it would be possible to just use the date portion of the StartTime <strong>TIMESTAMP </strong>for a "TotalHours-only"time record (and drop the WorkDate column altogether). The problem with this idea is that a <strong>TIMESTAMP </strong>always contains time information, whether or not you bother to fill in. If you assign only a date, then the time portion is presumed to be midnight. So there is no way to distinguish between a record where the user intended to fill in only total hours and one where the user intentionally filled in midnight as the StartTime but forgot to fill in the StopTime. That will be a problem when you validate the record prior to submitting it for payroll.</p>
<h2>Another way</h2>
<p>I found that the approach above works well for me, but those who find the duplication of one date completely untenable might be tempted to do something along the lines of this metadata:</p>
<blockquote>
<pre><code><strong>CREATE TABLE </strong>TimeRecords (
  Id <strong>INTEGER NOT NULL PRIMARY KEY</strong>,
  PersonId <strong>INTEGER </strong>[...],
  WorkDate <strong>DATE</strong>,
  StartTime <strong>TIME</strong>,
  StopTime </code><code><strong>TIMESTAMP</strong></code><code>,
  TotalHours <strong>NUMERIC</strong>(18, 4));</code></pre>
</blockquote>
<p>There&#8217;s no redundancy in this version. You can store both time records with start times and stop times or time records with just elapsed times, and it&#8217;s easy to distinguish the two. Unfortunately, certain queries become more difficult. With the version which uses <strong>TIMESTAMP </strong>for the StartTime column, I can write a query like this to determine who was in the building at a particular point in time:</p>
<blockquote>
<pre><code><strong>SELECT</strong>
  PersonId
<strong>FROM</strong>
  TimeRecords
<strong>WHERE</strong>
  :SomeParameter <strong>BETWEEN </strong>StartTime and StopTime</code></pre>
</blockquote>
<p>Records without start and stop times will be ignored by this query, since they do not contain enough information to answer the question. With a <strong>TIME </strong>instead of a <strong>TIMESTAMP </strong>data type for the StartTime column, I would have to use an expression in the where clause to write this query:</p>
<blockquote>
<pre><code><strong>SELECT</strong>
  PersonId
<strong>FROM</strong>
  TimeRecords
<strong>WHERE</strong>
  :SomeParameter <strong>BETWEEN </strong>(</code><code>WorkDate + </code><code>StartTime) and StopTime</code></pre>
</blockquote>
<p>That might well mean that my query can no longer be indexed.</p>
<h2>Conclusion</h2>
<p>Although my preferred schema has a small bit of redundancy, I find it significantly more usable.It is considerably less work to handle copying the date between the WorkDate and StartTime fields, and computing the TotalHours from the StartTime and StopTime, than it is to not have the date in either column.And not having dates in the StartTime and StopTime columns at all is just unusable.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37964&amp;akst_action=share-this" onclick="akst_share('37964', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F29%2F37964%2F', 'Data+Structures+for+Time+Records'); return false;" title="Post to del.icio.us, etc." id="akst_link_37964" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Data%20Structures%20for%20Time%20Records&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F29%2F37964%2F" id="akst_email_37964" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
  <item>
    <title>ASP.NET MVC TempData Is Really RedirectData</title>
    <link>http://blogs.teamb.com/craigstuntz/2009/01/23/37947/</link>
    <comments>http://blogs.teamb.com/craigstuntz/2009/01/23/37947/#comments</comments>
    <pubDate>Fri, 23 Jan 2009 16:30:38 +0000</pubDate>
    <dc:creator>Craig Stuntz</dc:creator>
    
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web]]></category>

    <guid isPermaLink="false">http://blogs.teamb.com/craigstuntz/?p=37947</guid>
    <description><![CDATA[Update: This post was written for MVC 1. TempData behaves completely differently in MVC 2 Beta and higher. In these versions, TempData is cleared only when it is read (or when the session expires).
Many people seem to be confused about the TempData feature in ASP.NET MVC. TempData behaves like the ViewData dictionary, except that it [...]]]></description>
      <content:encoded><![CDATA[<p><strong>Update:</strong> This post was written for MVC 1. TempData behaves completely differently in MVC 2 Beta and higher. In these versions, TempData is cleared only when it is read (or when the session expires).</p>
<p><a title="Questions containing tempdata" href="http://stackoverflow.com/search?q=tempdata">Many people seem to be confused about the TempData feature in ASP.NET MVC</a>. TempData behaves like the ViewData dictionary, <em>except </em>that it persists until the next request from the same browser.</p>
<p>Because of this, TempData should only be used when you know exactly what the next request is going to be. If you set TempData and your action then returns a ViewResult, then the next request, whatever it happens to be (an AJAX request, another page the user opened in a different tab, etc.), is going to see the TempData value you set, and no other request will see it. I&#8217;m guessing that this is never the behavior you want.</p>
<p><strong>Realistically, this means that you should only use TempData immediately before you redirect</strong> (in other words, immediately before you return a RedirectResult), because this is the only time when you are sure what the next request from that browser is going to be. I actually think that RedirectData would be a better name for this property. Someone, perhaps Steve McConnell, once noted that you should never include "temp" in a variable name, since variables are, by definition, temporary. "Temp data," to me, is synonymous with "variable." The (functionally similar) "flash" feature in Rails is even more badly named.</p>
<p>If your controller action returns a ViewResult, and you are tempted to put data into TempData, <strong>don&#8217;t</strong>. Use ViewData, instead, in this case.</p>
<p>This may lead to a situation where you might need to have a view look into both ViewData and TempData for a key. One example would be if you have an area in your Site.Master to display error messages on the page. It is likely that one controller action will need to send a message to the view via ViewData (because that action returns a ViewResult), while another action will need to send a message to the view via TempData (because that action returns a RedirectResult, as part of a <a href="http://blog.eworldui.net/post/2008/05/ASPNET-MVC---Using-Post2c-Redirect2c-Get-Pattern.aspx">POST/redirect/GET</a> cycle). In this case, you can use code like this in the Site.Master:</p>
<blockquote>
<pre><code>&lt;%= ViewData["Message"] ?? TempData["Message"] %&gt;</code></pre>
</blockquote>
<p>Under the hood, TempData works by using server-side Session state, so a distributed session cache like Velocity can be used if your application runs on a server farm. Since the lifetime of data put into TempData is limited to the next request, it is fairly easy to use without worrying about growing the session very large, especially since the most common use for TempData is to store a short error string. But the usual rules on what you can put into a Session apply. If you set the <a href="http://msdn.microsoft.com/en-us/library/ms178586.aspx">Session state mode</a> to out of process, then the data you put in it must be serializable.</p>
<p class="akst_link"><a href="http://blogs.teamb.com/craigstuntz/?p=37947&amp;akst_action=share-this" onclick="akst_share('37947', 'http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F23%2F37947%2F', 'ASP.NET+MVC+TempData+Is+Really+RedirectData'); return false;" title="Post to del.icio.us, etc." id="akst_link_37947" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=ASP.NET%20MVC%20TempData%20Is%20Really%20RedirectData&body=Have you seen this? http%3A%2F%2Fblogs.teamb.com%2Fcraigstuntz%2F2009%2F01%2F23%2F37947%2F" id="akst_email_37947" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
      <wfw:commentRss></wfw:commentRss>
    </item>
</channel>
</rss>
<!-- 452 queries 4.015 seconds. -->
