<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
    <channel>
        <title>Matt Hidinger</title>
        <link>http://www.matthidinger.com/Default.aspx</link>
        <description>On Error GoTo Blog</description>
        <language>en-US</language>
        <copyright>Matt Hidinger</copyright>
        <managingEditor>matt.hidinger@gmail.com</managingEditor>
        <generator>Subtext Version 2.1.0.5</generator>
        <image>
            <title>Matt Hidinger</title>
            <url>http://www.matthidinger.com/images/RSS2Image.gif</url>
            <link>http://www.matthidinger.com/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/mhidinger" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
            <title>Yet Another Yield Rant</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/GNsd1o3EeIU/yet-another-yield-rant.aspx</link>
            <description>&lt;p&gt;This post was spawned as I was reviewing the latest &lt;a href="http://oxite.codeplex.com/SourceControl/changeset/view/43567#709744" target="_blank"&gt;Oxite source code&lt;/a&gt; on &lt;a href="http://oxite.codeplex.com" target="_blank"&gt;CodePlex&lt;/a&gt;. I’ve been reading any source code I could get my hands on lately looking for inspiration to cure my “winter coding boredom.” While it isn’t winter yet, it is fast approaching, which means less outdoors time and more computer time. I try to blog more, update my open source projects with a new release, and with any luck begin a new project worth getting passionate about. &lt;/p&gt;  &lt;p&gt;Today I'm going to hit the ground running with a short tip, again, on the yield keyword.&lt;/p&gt;  &lt;p&gt;The following code is an excerpt from the Oxite Blog class. Blog as it turns out, is a Cacheable Entity (ICacheEntity) where the designer of the interface determined that cached entities can specify any dependencies they may have. Clearly, the developer of the ICacheEntity interface understood iterators and realized that the consumer of any ICacheEntity requires nothing more foreach’ing over the dependencies. For this reason, the method does not return an IList&amp;lt;T&amp;gt;, an ICollection&amp;lt;T&amp;gt;, or (heaven forbid) a List&amp;lt;T&amp;gt;.&lt;/p&gt;  &lt;p&gt;Unfortunately, the developer writing the Blog class did not take advantage of the (albeit minor) utility provided. The developer chose to new up a List, insert the single item, then return the list -- as seen in the following code.&lt;/p&gt;   &lt;pre class="brush: c#"&gt;IEnumerable&amp;lt;ICacheEntity&amp;gt; ICacheEntity.GetCacheDependencyItems()
{
    List&amp;lt;ICacheEntity&amp;gt; dependencies = new List&amp;lt;ICacheEntity&amp;gt;();

    dependencies.Add(Site);

    return dependencies;
}&lt;/pre&gt;

&lt;p&gt;We've all written code like this. The bad habit may even be so ingrained into our developer DNA that we don't even realize it. &lt;em&gt;Long story short, if it returns IEnumerable, you should probably use the yield keyword!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The above code can simply be re-written as follows. The benefits of this should be clear: fewer lines of code, easier readability, greater performance (minor of course, but still).  Since this topic has been covered &lt;a href="http://lmgtfy.com/?q=c%23+yield" target="_blank"&gt;at great length&lt;/a&gt; on the blogosphere I won't go into any more detail, but just in case, &lt;a href="http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html" target="_blank"&gt;here is a quick article&lt;/a&gt; I found that should help explain the benefits. &lt;/p&gt;

&lt;pre class="brush: c#"&gt;IEnumerable&amp;lt;ICacheEntity&amp;gt; ICacheEntity.GetCacheDependencyItems()
{
     yield return Site;
}&lt;/pre&gt;

&lt;p /&gt;

&lt;h3&gt;Bonus Protip&lt;/h3&gt;

&lt;p&gt;I actually stumbled onto something small but nice while reading the Oxite code. Enumerable.Empty.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;IEnumerable&amp;lt;Product&amp;gt; products = Enumerable.Empty&amp;lt;Product&amp;gt;;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:945a1706-1d0e-4ddf-9d6c-4bd22ac1fdb3" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/37.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/GNsd1o3EeIU" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/09/22/yet-another-yield-rant.aspx</guid>
            <pubDate>Tue, 22 Sep 2009 05:01:25 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/37.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/09/22/yet-another-yield-rant.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/37.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/37.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/09/22/yet-another-yield-rant.aspx</feedburner:origLink></item>
        <item>
            <title>Automatically roll back your LINQ to SQL integration tests</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/TKBo4tKMqRY/automatically-roll-back-your-linq-to-sql-integration-tests.aspx</link>
            <description>&lt;p&gt;Today I began integration testing my SqlRepository while I experiment with an MVC prototype. I tried googling for a simple base class for integration testing a LINQ to SQL DataContext that would provide automatic rollback between each test, but after (minimal) searching, decided to simply write my own. Perhaps this will help someone. This base class was written for MS Test, but simply renaming the attributes accordingly would yield the same results on nUnit, xUnit, etc.&lt;/p&gt;  &lt;h3&gt;The Code&lt;/h3&gt;  &lt;p&gt;Simply inherit your test class from this base class and any changes done via the internal Context property will be automatically rolled back after each test runs.&lt;/p&gt;  &lt;pre class="brush: c#"&gt;/// &amp;lt;summary&amp;gt;
/// The base class will allow LINQ to SQL integration testing with automatic rollbacks after each test
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name="TContext"&amp;gt;The type of data context to use&amp;lt;/typeparam&amp;gt;
public abstract class RolledBackDataContextTests&amp;lt;TContext&amp;gt; where TContext : DataContext
{
    private TContext _context;
    private DbTransaction _transaction;

    [TestInitialize]
    public void InitDataContext()
    {
        if(string.IsNullOrEmpty(ConnectionString))
        {
            _context = (TContext)Activator.CreateInstance(typeof(TContext));
        }
        else
        {
            _context = (TContext) Activator.CreateInstance(typeof (TContext), ConnectionString);
        }

        _context.Connection.Open();
        _transaction = _context.Connection.BeginTransaction();
        _context.Transaction = _transaction;
    }

    /// &amp;lt;summary&amp;gt;
    /// Provides access to the internal data context. Any changes made will be automatically rolled back
    /// &amp;lt;/summary&amp;gt;
    protected TContext Context
    {
        get
        {
            if(_context == null)
                InitDataContext();

            return _context;
        }
    }

    /// &amp;lt;summary&amp;gt;
    /// Optionally specify the connection string to use
    /// &amp;lt;/summary&amp;gt;
    protected virtual string ConnectionString
    {
        get
        {
            return null;
        }
    }

    [TestCleanup]
    public void TestCleanup()
    {
        _transaction.Rollback();
        _context.Dispose();
        _context = null;
    }
}
&lt;/pre&gt;

&lt;h3&gt;Usage&lt;/h3&gt;

&lt;pre class="brush: c#"&gt;[TestClass]
public class SqlRepositoryTests : RolledBackDataContextTests&amp;lt;NorthwindDataContext&amp;gt;
{
    // Insert as many Products as required and then exercise your database integration Test Methods
    public void InsertProductToContext()
    {
        Product p = new Product { ProductName = "Temporary Product"};
        Context.Products.InsertOnSubmit(p);
        Context.SubmitChanges();

        // After each test ends, the transaction will be rolled back, and the new Product will not be in the database
    }

    [TestMethod]
    public void Test1()
    {
        // Test logic here
    }
}&lt;/pre&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ce342ad5-610e-4823-88d7-a32ede9fe532" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/LINQ+to+SQL" rel="tag"&gt;LINQ to SQL&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Unit+Testing" rel="tag"&gt;Unit Testing&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/35.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/TKBo4tKMqRY" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/09/08/automatically-roll-back-your-linq-to-sql-integration-tests.aspx</guid>
            <pubDate>Wed, 09 Sep 2009 03:59:51 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/35.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/09/08/automatically-roll-back-your-linq-to-sql-integration-tests.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/35.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/35.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/09/08/automatically-roll-back-your-linq-to-sql-integration-tests.aspx</feedburner:origLink></item>
        <item>
            <title>Creating a simple ToDelimitedString extension method</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/r_jAyPxrvRI/creating-a-simple-todelimitedstring-extension-method.aspx</link>
            <description>&lt;p&gt;This was one of the first extension methods I wrote when C# 3.0 arrived, since I just stumbled across it on an older project I figured I might as well post it, if for nothing else but future reference. One downside to be aware of if you choose to use this method, is that it will not project the results on a IQueryable provider like LINQ to SQL, so please be aware the conversion will be done on the client side. &lt;/p&gt;  &lt;h3&gt;The Code&lt;/h3&gt;  &lt;pre class="brush: c#"&gt;public static class DelimitedStringExtensions
{
    public static string DefaultDelimiter = ", ";

    /// &amp;lt;summary&amp;gt;
    /// Convert a sequence of items to a delimited string. By default, ToString() will be called on each item in the sequence to formulate the result. The default delimiter of ', ' will be used
    /// &amp;lt;/summary&amp;gt;
    public static string ToDelimitedString&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; source)
    {
        return source.ToDelimitedString(x =&amp;gt; x.ToString(), DefaultDelimiter);
    }

    /// &amp;lt;summary&amp;gt;
    /// Convert a sequence of items to a delimited string. By default, ToString() will be called on each item in the sequence to formulate the result
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="delimiter"&amp;gt;The delimiter to separate each item with&amp;lt;/param&amp;gt;
    public static string ToDelimitedString&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; source, string delimiter)
    {
        return source.ToDelimitedString(x =&amp;gt; x.ToString(), delimiter);
    }

    /// &amp;lt;summary&amp;gt;
    /// Convert a sequence of items to a delimited string. The default delimiter of ', ' will be used
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="selector"&amp;gt;A lambda expression to select a string property of &amp;lt;typeparamref name="T"/&amp;gt;&amp;lt;/param&amp;gt;
    public static string ToDelimitedString&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; source, Func&amp;lt;T, string&amp;gt; selector)
    {
        return source.ToDelimitedString(selector, DefaultDelimiter);
    }

    /// &amp;lt;summary&amp;gt;
    /// Convert a sequence of items to a delimited string.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="selector"&amp;gt;A lambda expression to select a string property of &amp;lt;typeparamref name="T"/&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="delimiter"&amp;gt;The delimiter to separate each item with&amp;lt;/param&amp;gt;
    public static string ToDelimitedString&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; source, Func&amp;lt;T, string&amp;gt; selector, string delimiter)
    {
        if (source == null)
            return string.Empty;

        if(selector == null)
            throw new ArgumentNullException("selector", "Must provide a valid property selector");

        if (string.IsNullOrEmpty(delimiter))
            delimiter = DefaultDelimiter;

        return string.Join(delimiter, source.Select(selector).ToArray());
    }
}&lt;/pre&gt;

&lt;h3&gt;Usage&lt;/h3&gt;

&lt;p&gt;Example using an array of ints&lt;/p&gt;

&lt;pre class="brush: c#"&gt;int[] ints = { 1, 4, 5, 7 };

// Returns "1, 4, 5, 7"
string result = ints.ToDelimitedString();
&lt;/pre&gt;

&lt;p&gt;Example using a List&lt;product /&gt;&lt;/p&gt;

&lt;pre class="brush: c#"&gt;var products = new List&amp;lt;Product&amp;gt;
               {
                   new Product { ProductName = "Chai" },
                   new Product { ProductName = "Chang" },
                   new Product { ProductName = "Tofu" },
               };

// Returns "Chai, Chang, Tofu"
string result1 = products.ToDelimitedString(p =&amp;gt; p.ProductName);


// Returns "Chai;Chang;Tofu"
string result2 = products.ToDelimitedString(p =&amp;gt; p.ProductName, ";");

&lt;/pre&gt;

&lt;p&gt;Example using a DataTable&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
// Returns "Chai, Chang, Tofu"
string result = table.AsEnumerable().ToDelimitedString(row =&amp;gt; (string)row["ProductName"]);

&lt;/pre&gt;


&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:12a39fcc-c64f-472d-8b3e-6c9f79cbafab" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/LINQ" rel="tag"&gt;LINQ&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/34.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/r_jAyPxrvRI" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/09/07/creating-a-simple-todelimitedstring-extension-method.aspx</guid>
            <pubDate>Tue, 08 Sep 2009 02:55:32 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/34.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/09/07/creating-a-simple-todelimitedstring-extension-method.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/34.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/34.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/09/07/creating-a-simple-todelimitedstring-extension-method.aspx</feedburner:origLink></item>
        <item>
            <title>Convention based LINQ querying</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/yx3nNabHdhs/convention-based-linq-querying.aspx</link>
            <description>&lt;p&gt;LINQ and Expression Trees have enabled a ton of possibilities for us as developers, particularly in establishing some code-reducing convention based querying. I have found myself playing with Expressions in C# since their inception and will hopefully be publishing a few other posts I have queued up. For now, this post will simply demonstrate how to take advantage of a popular convention whereby each database table always has a single integer primary key named “Id”&lt;/p&gt;  &lt;p&gt;By taking advantage of this primary key convention I can save myself a ton of boilerplate code to query a table by ID.&lt;/p&gt;  &lt;h3&gt;The Extension Method&lt;/h3&gt;  &lt;pre class="brush: c#"&gt;public static T GetById&amp;lt;T&amp;gt;(this IQueryable&amp;lt;T&amp;gt; query, int id) where T : class
{
    // Create lambda parameter x of type T
    var param = Expression.Parameter(typeof(T), "x");

    // Given x param, extract the Id property
    var memberExpression = Expression.Property(param, "Id");

    // Build Lambda expression
    // x =&amp;gt; x.Id == id
    var whereClause =
        Expression.Lambda&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt;(
            Expression.Equal(
                memberExpression,
                Expression.Constant(id)
                ), param);

    return query.Single(whereClause);
}&lt;/pre&gt;

&lt;h3&gt;Usage&lt;/h3&gt;

&lt;pre class="brush: c#"&gt;NorthwindDataContext db = new NorthwindDataContext();
var product = db.Products.GetById(1);
var order = db.Orders.GetById(15);&lt;/pre&gt;

&lt;p /&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ce9c4ad2-21ca-40ae-91b9-b527c3e5b68c" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/LINQ" rel="tag"&gt;LINQ&lt;/a&gt;,&lt;a href="http://technorati.com/tags/LINQ+to+SQL" rel="tag"&gt;LINQ to SQL&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Expression+Trees" rel="tag"&gt;Expression Trees&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/33.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/yx3nNabHdhs" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/09/04/convention-based-linq-querying.aspx</guid>
            <pubDate>Fri, 04 Sep 2009 19:14:42 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/33.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/09/04/convention-based-linq-querying.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/33.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/33.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/09/04/convention-based-linq-querying.aspx</feedburner:origLink></item>
        <item>
            <title>Creating a Html.DisplayForMany Helper for MVC 2</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/M8ifIEnIFSc/creating-a-html.displayformany-helper-for-mvc-2.aspx</link>
            <description>&lt;p&gt;&lt;strong&gt;Note: This article was written for ASP.NET MVC 2 Preview 1 – it may become outdated in future previews.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The Html helper in ASP.NET MVC 2 comes with some handy methods called “DisplayFor” and “EditFor” – please see &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx" target="_blank"&gt;Scott Gu’s&lt;/a&gt; article if you are not familiar with these new features. Long story short, they provide an ASP.NET Dynamic Data-like mechanism which uses reflection and templating to render a display form or an edit form. It works great for primitive properties like String, DataTime, Int32, as well as complex types like “Address.” However, as I was playing with them, I came across a rather funny exception (excusable, I suppose, due to the preview state of MVC 2 at the time of this writing).&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;blockquote&gt;   &lt;h4&gt;&lt;i&gt;This exception should never occur.&lt;/i&gt;&lt;/h4&gt;   &lt;b&gt;Description: &lt;/b&gt;An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.     &lt;br /&gt;&lt;b&gt;Exception Details: &lt;/b&gt;System.InvalidOperationException: This exception should never occur.     &lt;br /&gt;&lt;b&gt;Source Error:&lt;/b&gt;     &lt;pre&gt;Line 5:  &amp;lt;%= Html.DisplayFor(m =&amp;gt; m.Comments) %&amp;gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;This error occurs because the “Comments” property is an &lt;strong&gt;IList&amp;lt;Comment&amp;gt;&lt;/strong&gt; – the DisplayFor() method choked because the property type is an interface rather than a concrete class that of course derives from System.Object – which is where the DisplayFor reflection magic comes from. However, that wasn’t really my problem, I could work around that and make my property a List&amp;lt;Comment&amp;gt; instead of IList&amp;lt;Comment&amp;gt; (as a workaround). After this change, the exception is gone, but the results are not what I needed.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Capacity: 2&lt;/p&gt;

  &lt;p&gt;Count: 2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is what ended up being rendered on my page, which makes sense – DisplayFor() reflected on the 2 public properties of the List&amp;lt;T&amp;gt; type and displayed them for me. What I really wanted to do however, was iterate over the list and call DisplayFor() on each individual item.&lt;/p&gt;

&lt;h3&gt;Enter the DisplayForMany extension method.&lt;/h3&gt;

&lt;p&gt;The code is longer than I would like due to a number of complications and restrictions in the current DisplayFor extension methods and internal classes that would have been handy to have access to. The comments hopefully explain the workarounds, but in any case, just copy this code into your helper class and enjoy.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;public static string DisplayForMany&amp;lt;TModel, TValue&amp;gt;(this HtmlHelper&amp;lt;TModel&amp;gt; html, Expression&amp;lt;Func&amp;lt;TModel, IEnumerable&amp;lt;TValue&amp;gt;&amp;gt;&amp;gt; expression) where TModel : class
{
    StringBuilder sb = new StringBuilder();

    // Get the items from ViewData
    var items = expression.Compile()(html.ViewData.Model);


    foreach(TValue item in items)
    {
        // Current html.DisplayFor() throws exception if the expression is anything that isn't a "MemberAccessExpression"
        // So we have to trick it and place the item into a dummy wrapper and access the item through a Property
        var dummy = new {Item = item};

        // Get the actual item by accessing the "Item" property from our dummy class
        var memberExpression = Expression.MakeMemberAccess(Expression.Constant(dummy), dummy.GetType().GetProperty("Item"));

        // Create a lambda expression passing the MemberExpression to access the "Item" property and the expression params
        var singleItemExpression = Expression.Lambda&amp;lt;Func&amp;lt;TModel, TValue&amp;gt;&amp;gt;(memberExpression,
                                                                           expression.Parameters);

        string singleItemHtml = html.DisplayFor(singleItemExpression);
        sb.AppendFormat(singleItemHtml);    
    }

    return sb.ToString();
}&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Usage and Output&lt;/h3&gt;

&lt;pre class="brush: c#"&gt;&amp;lt;h3&amp;gt;Comments&amp;lt;/h3&amp;gt;
&amp;lt;%= Html.DisplayForMany(m =&amp;gt; m.Comments) %&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://www.matthidinger.com/contentimages/CreatingaHtm.DisplayForManyHelperforMVC2_1164D/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.matthidinger.com/contentimages/CreatingaHtm.DisplayForManyHelperforMVC2_1164D/image_thumb.png" width="1223" height="468" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9282bddd-2c70-44e4-b8d9-dc08b12a51df" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/ASPNET+MVC" rel="tag"&gt;ASPNET MVC&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/32.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/M8ifIEnIFSc" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/08/15/creating-a-html.displayformany-helper-for-mvc-2.aspx</guid>
            <pubDate>Sun, 16 Aug 2009 00:47:27 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/32.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/08/15/creating-a-html.displayformany-helper-for-mvc-2.aspx#feedback</comments>
            <slash:comments>6</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/32.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/32.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/08/15/creating-a-html.displayformany-helper-for-mvc-2.aspx</feedburner:origLink></item>
        <item>
            <title>DoddleImport on CodePlex</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/U_kg_IDurWo/doddleimport-on-codeplex.aspx</link>
            <description>&lt;p&gt;Well I am heading out to Myrtle Beach tonight at 4am, so I spent today finishing up some cleanup so I could release DoddleImport on CodePlex. It should be pretty feature complete and ready for use, and as always, please let me know if it helps you out!&lt;/p&gt;  &lt;h3&gt;Objective &lt;/h3&gt;  &lt;p&gt;Flexible importing of data via a fluid and fully extensible API to easily add support for new Import Sources and Import Destinations.&lt;/p&gt;  &lt;p&gt;I will update the documentation and provide some better examples when I get back. Here you can see a quick example of me importing some Excel data into a SharePoint list. As you can see it supports a variety of validation including missing fields and data type conversion problems.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.matthidinger.com/ContentImages/DoddleImportonCodePlex_14E69/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.matthidinger.com/ContentImages/DoddleImportonCodePlex_14E69/image_thumb.png" width="532" height="432" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.matthidinger.com/ContentImages/DoddleImportonCodePlex_14E69/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.matthidinger.com/ContentImages/DoddleImportonCodePlex_14E69/image_thumb_3.png" width="891" height="198" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Key Components &lt;/h3&gt;  &lt;p&gt;Importing relies on 2 distinct (and entirely extensible) mechanisms:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;b&gt;IImportSource&lt;/b&gt; - The import framework requires a set of row/field data provided via an IImportSource &lt;/li&gt;    &lt;li&gt;&lt;b&gt;IImportDestination&lt;/b&gt; - The import framework requires a destination to write the data to via an IImportDestination &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;Note: Most "importable" classes implement both IImportSource as well as IImportDestination, as such, can be used as a source of import rows and a destination to import into &lt;/blockquote&gt;  &lt;h3&gt;Import Sources and Destinations &lt;/h3&gt; DoddleImport ships with some basic Import Sources, but just like all other Doddle Projects, you can easily create your own by implementing a simple interface.   &lt;ul&gt;   &lt;li&gt;&lt;b&gt;ImportableCollection&lt;/b&gt; - provides importing to and from a generic list &lt;/li&gt;    &lt;li&gt;&lt;b&gt;ImportableDictionary&lt;/b&gt; - provides importing to and from a basic dictionary &lt;/li&gt;    &lt;li&gt;&lt;b&gt;ImportableSPList&lt;/b&gt; - provides importing to and from a SharePoint List &lt;/li&gt;    &lt;li&gt;&lt;b&gt;Spreadsheet&lt;/b&gt; - provides importing from an Excel Spreadsheet &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Usage&lt;/h3&gt;  &lt;pre class="brush: c#"&gt;// Basic import from one type of in-memory collection to another
ImportableDictionary source = new ImportableDictionary();
source.Fields.Add("ProductID", typeof(int));
source.Fields.Add("ProductName", typeof(string));

IDictionary row1 = source.AddRow();
row1["ProductID"] = 1;
row1["ProductName"] = "My Product";

List&lt;product&gt; products = new List&amp;lt;Product&amp;gt;();
IImportDestination destination = new ImportableCollection&amp;lt;Product&amp;gt;(products);

Importer importer = new Importer();
importer.Import(source, destination);&lt;/product&gt;&lt;/pre&gt;

&lt;pre class="brush: c#"&gt;// More realistic example, importing an Excel Spreadsheet into a SharePoint list
Stream uploadedFile = fileUpload.PostedFile.InputStream;
Spreadsheet spreadsheet = new Spreadsheet(uploadedFile);

SPList myList = Web.Lists["My List"];
IImportDestination destination = new ImportableSPList(myList);

Importer importer = new Importer();
importer.Import(spreadsheet, destination);&lt;/pre&gt;

&lt;h3&gt;Validation &lt;/h3&gt;

&lt;p&gt;DoddleImport will provide automatic validation of your Import Source against the specified destination. This ensures that the entire import contents will be successfully imported as well as provide helpful error messages to your user so they can easily correct errors.&lt;/p&gt;

&lt;h4&gt;Validation Rules &lt;/h4&gt;
The validation mechanism works by automatically evaluating rules against each row being imported. This is handled through the IValidationRule interface. 

&lt;ul&gt;
  &lt;li&gt;The default rules with DoddleImport are as follows: 
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;RequiredFieldsRule&lt;/b&gt; - validates a row to make sure that data was provided for all required fields &lt;/li&gt;

      &lt;li&gt;&lt;b&gt;MissingHeadersRule&lt;/b&gt; - validates that the source contains all required fields that the destination expects &lt;/li&gt;

      &lt;li&gt;&lt;b&gt;DataTypeValidationRule&lt;/b&gt; - valdiates data type mis-match errors &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Configuration &lt;/h3&gt;

&lt;p&gt;If you want to change some of th default behavior of DoddleImport then using your application configuration file is the best place to start.&lt;/p&gt;

&lt;p&gt;To use configuration, be sure to register the &amp;lt;section&amp;gt; node between &amp;lt;configSections&amp;gt; in your app.Config or web.Config&lt;/p&gt;

&lt;p&gt;From there, you can add or remove validation rules that will be automatically applied to every import. You are also able to customize the default validation messages. Below is a quick sample of some of the changes that can be made. &lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name="doddleImport" 
          type="Doddle.Import.Configuration.ImportSection, Doddle.Import, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f5f0fd458d019c9" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;doddleImport&amp;gt;
    &amp;lt;validation&amp;gt;
      &amp;lt;rules&amp;gt;
        &amp;lt;remove name="MissingHeadersRule" /&amp;gt;
        &amp;lt;add name="MyCustomRule" type="MyName.Importing.CustomValidationRule, MyName.Importing" /&amp;gt;
      &amp;lt;/rules&amp;gt;
      &amp;lt;messages&amp;gt;
        &amp;lt;remove rule="RequiredFieldsRule" /&amp;gt;
        &amp;lt;add rule="RequiredFieldsRule" message="Unable to locate field '{0}'"/&amp;gt;
      &amp;lt;/messages&amp;gt;
    &amp;lt;/validation&amp;gt;
  &amp;lt;/doddleImport&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;That's all for now, check back for updates on this and some other projects. 
  &lt;br /&gt;&lt;/p&gt;

&lt;h3&gt;Get the Source and Try it out!&lt;/h3&gt;

&lt;br /&gt;&lt;a href="http://codeplex.com/doddleimport" target="_blank"&gt;Check it out at CodePlex&lt;/a&gt;

&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;
  &lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:dfc63c95-16da-4d4a-9eba-d46f1febfd9a" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Doddle" rel="tag"&gt;Doddle&lt;/a&gt;,&lt;a href="http://technorati.com/tags/SharePoint" rel="tag"&gt;SharePoint&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/25.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/U_kg_IDurWo" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/02/28/doddleimport-on-codeplex.aspx</guid>
            <pubDate>Sun, 01 Mar 2009 05:47:10 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/25.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/02/28/doddleimport-on-codeplex.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/25.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/25.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/02/28/doddleimport-on-codeplex.aspx</feedburner:origLink></item>
        <item>
            <title>WCSF ObjectContainerDataSource with LINQ to SQL</title>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/6C66omM-fB4/wcsf-objectcontainerdatasource-with-linq-to-sql.aspx</link>
            <description>&lt;p&gt;A project I am now working on is using the &lt;a href="http://www.codeplex.com/websf" target="_blank"&gt;Web Client Software Factory&lt;/a&gt; (WCSF) from the &lt;a href="http://msdn.microsoft.com/practices" target="_blank"&gt;patterns &amp;amp; practices&lt;/a&gt; team. It is basically an elaborate MVP-based framework that currently sits on top of ASP.NET Webforms. &lt;/p&gt;  &lt;p&gt;One of the components it ships with is the &lt;strong&gt;ObjectContainerDataSource&lt;/strong&gt; which is a lot like the ObjectDataSource that ASP.NET provides. I admittedly have little experience with either of these controls, since I am not a huge fan of declarative data binding in larger applications. It does however offer better integration with the MVP pattern, simplifying the “bubbling” of DataSource events up to the Presenter to handle them. The Presenter is of course where all of the logic for the view and its services belongs.&lt;/p&gt;  &lt;p&gt;At first everything was working great: selects, server-side paging, server-side sorting, even inserting. But when I tried some Updates and Deletes with the GridView and the ObjectContainerDataSource I was encountering a frustrating exception I hadn’t seen before.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;Row not found or changed.&lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The exception was being thrown on the dataContext.SubmitChanges(). After some quick digging I found that this error is due to our Timestamp column which is used by the LinqDataContext for optimistic concurrency. Before the Data Source fires its Updated event, it re-creates an instance of the object and populates the properties with the values in the data control using reflection. However, the ObjectContainterDataSource was not setting the Timestamp property when it was re-constructing the object for updating. This was causing the LinqDataContext to throw the “Row not Found” exception because it could not find a row WHERE ContractorId = 1 AND Timestamp = NULL. I needed some way to persist the Timestamp property within the DataSource so it would re-populate it on the Updated event. &lt;/p&gt;  &lt;pre class="brush: sql; highlight: 5"&gt;exec sp_executesql N'UPDATE [dbo].[Contractors] 
SET [ContractorName] = @p2 WHERE ([ContractorId] = @p0) AND ([Timestamp] = @p1) 

@p0=1,
@p1=NULL,
@p2='My Updated Contractor'&lt;/pre&gt;

&lt;p&gt;The solution I found, was to include the Timestamp column in the DataKeyNames property. This ensured that the data source would correctly populate the property even though it did not appear as a column in my GridView.&lt;/p&gt;

&lt;pre class="brush: xhtml; highlight: [3]"&gt;&amp;lt;asp:GridView ID="ContractorGrid" runat="server" 
    AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
    DataSourceID="ContractorDataSource" DataKeyNames="ContractorId, Timestamp"
    PageSize="5" AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false"&amp;gt;&lt;/pre&gt;

&lt;p&gt;This may be a well-known problem with LINQ to SQL and the DataSources, but as I mentioned I don’t use them that much for declarative data binding. Either way, hopefully this saves someone frustration down the road.
  &lt;br /&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2c0d99d3-67c1-4ae8-b62d-18aea32d576a" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/WCSF" rel="tag"&gt;WCSF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/LINQ+to+SQL" rel="tag"&gt;LINQ to SQL&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/21.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/6C66omM-fB4" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/02/19/wcsf-objectcontainerdatasource-with-linq-to-sql.aspx</guid>
            <pubDate>Thu, 19 Feb 2009 20:49:06 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/21.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/02/19/wcsf-objectcontainerdatasource-with-linq-to-sql.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/21.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/21.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/02/19/wcsf-objectcontainerdatasource-with-linq-to-sql.aspx</feedburner:origLink></item>
        <item>
            <title>ASP.NET MVC Recursive TreeView Helper</title>
            <category>jQuery</category>
            <category>ASPNET MVC</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/S7s_omvvvs4/asp.net-mvc-recursive-treeview-helper.aspx</link>
            <description>&lt;p&gt;&lt;strong&gt;Update 2/10/2009: I have updated the helper code a little bit to include an ID parameter as well as to inject the jQuery treeview script code automatically. Please modify to your desire, or make sure to include the jQuery TreeView plugin script to your page before running.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following helper will make it easy to create a tree view from a recursive self-referencing table. Below you are seeing a tree of “Locations” where each Location can contain X number of child locations.&lt;/p&gt;
&lt;h3&gt;Dependencies&lt;/h3&gt;
&lt;p&gt; &lt;a title="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/" target="_blank" href="http://bassistance.de/jquery-plugins/jquery-plugin-treeview/"&gt;jQuery TreeView Plugin&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;br /&gt;
Rendered Tree&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="159" height="299" src="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image_thumb.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Table Definition&lt;/h3&gt;
&lt;p&gt;The table itself is extremely simple, each Location has a ParentLocationId which is a relationship to the same table. If the ParentLocationId is null then it is a root location.&lt;/p&gt;
&lt;p&gt; &lt;a href="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image_3.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="345" height="337" src="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image_thumb_3.png" /&gt;&lt;/a&gt; &lt;a href="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image_4.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="399" height="125" src="http://blog2.matthidinger.com/ContentImages/ASP.NETMVCRecursiveTreeViewHelper_B445/image_thumb_4.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;&lt;br /&gt;
Usage &lt;br /&gt;
&lt;/h3&gt;
&lt;p&gt;Simple &lt;/p&gt;
&lt;pre class="brush: c#"&gt;&amp;lt;%= Html.TreeView("locations", 
    Model.Locations, 
    l =&amp;gt; l.ChildrenLocations, 
    l =&amp;gt; l.Name) %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Wrapping a div around each list item&lt;/p&gt;
&lt;pre class="brush: c#"&gt;&amp;lt;%= Html.TreeView("dropTree", 
    Model.Locations, 
    l =&amp;gt; l.ChildrenLocations, 
    l =&amp;gt; "&amp;lt;div class='dropZone'&amp;gt;" + l.Name + "&amp;lt;div&amp;gt;")
&lt;/pre&gt;
&lt;p&gt;Making each list item an ActionLink&lt;/p&gt;
&lt;pre class="brush: c#"&gt;&amp;lt;%= Html.TreeView("dropTree", 
    Model.Locations, 
    l =&amp;gt; l.ChildrenLocations, 
    l =&amp;gt; Html.ActionLink("MyController", "MyAction", l.Name, new { id = l.Name })
&lt;/pre&gt;
&lt;h3&gt;The Code&lt;/h3&gt;
&lt;pre class="brush: c#"&gt;public static class TreeViewHtmlHelper
{
    /// &amp;lt;summary&amp;gt;
    /// Create a TreeView of nodes starting from a root element
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="treeId"&amp;gt;The ID that will be used when the ul is created&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="rootItems"&amp;gt;The root nodes to create&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="childrenProperty"&amp;gt;A lambda expression that returns the children nodes&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="itemContent"&amp;gt;A lambda expression defining the content in each tree node&amp;lt;/param&amp;gt;
    public static string TreeView&amp;lt;T&amp;gt;(this HtmlHelper html, string treeId, IEnumerable&amp;lt;T&amp;gt; rootItems, Func&amp;lt;T, IEnumerable&amp;lt;T&amp;gt;&amp;gt; childrenProperty, Func&amp;lt;T, string&amp;gt; itemContent)
    {
        return html.TreeView(treeId, rootItems, childrenProperty, itemContent, true, null);
    }

    /// &amp;lt;summary&amp;gt;
    /// Create a TreeView of nodes starting from a root element
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="treeId"&amp;gt;The ID that will be used when the ul is created&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="rootItems"&amp;gt;The root nodes to create&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="childrenProperty"&amp;gt;A lambda expression that returns the children nodes&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="itemContent"&amp;gt;A lambda expression defining the content in each tree node&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="includeJavaScript"&amp;gt;If true, output will automatically render the JavaScript to turn the ul into the treeview&amp;lt;/param&amp;gt;    
    public static string TreeView&amp;lt;T&amp;gt;(this HtmlHelper html, string treeId, IEnumerable&amp;lt;T&amp;gt; rootItems, Func&amp;lt;T, IEnumerable&amp;lt;T&amp;gt;&amp;gt; childrenProperty, Func&amp;lt;T, string&amp;gt; itemContent, bool includeJavaScript)
    {
        return html.TreeView(treeId, rootItems, childrenProperty, itemContent, includeJavaScript, null);
    }

    /// &amp;lt;summary&amp;gt;
    /// Create a TreeView of nodes starting from a root element
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="treeId"&amp;gt;The ID that will be used when the ul is created&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="rootItems"&amp;gt;The root nodes to create&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="childrenProperty"&amp;gt;A lambda expression that returns the children nodes&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="itemContent"&amp;gt;A lambda expression defining the content in each tree node&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="includeJavaScript"&amp;gt;If true, output will automatically render the JavaScript to turn the ul into the treeview&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="emptyContent"&amp;gt;Content to be rendered when the tree is empty&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="includeJavaScript"&amp;gt;If true, output will automatically into the JavaScript to turn the ul into the treeview&amp;lt;/param&amp;gt;    
    public static string TreeView&amp;lt;T&amp;gt;(this HtmlHelper html, string treeId, IEnumerable&amp;lt;T&amp;gt; rootItems, Func&amp;lt;T, IEnumerable&amp;lt;T&amp;gt;&amp;gt; childrenProperty, Func&amp;lt;T, string&amp;gt; itemContent, bool includeJavaScript, string emptyContent)
    {
        StringBuilder sb = new StringBuilder();

        sb.AppendFormat("&amp;lt;ul id='{0}'&amp;gt;\r\n", treeId);

        if(rootItems.Count() == 0)
        {
            sb.AppendFormat("&amp;lt;li&amp;gt;{0}&amp;lt;/li&amp;gt;", emptyContent);
        }

        foreach (T item in rootItems)
        {
            RenderLi(sb, item, itemContent);
            AppendChildren(sb, item, childrenProperty, itemContent);
        }

        sb.AppendLine("&amp;lt;/ul&amp;gt;");

        if (includeJavaScript)
        {
            sb.AppendFormat(
                @"&amp;lt;script type='text/javascript'&amp;gt;
                    $(document).ready(function() {{
                        $('#{0}').treeview({{ animated: 'fast' }});
                    }});
                &amp;lt;/script&amp;gt;", treeId);
        }

        return sb.ToString();
    }

    private static void AppendChildren&amp;lt;T&amp;gt;(StringBuilder sb, T root, Func&amp;lt;T, IEnumerable&amp;lt;T&amp;gt;&amp;gt; childrenProperty, Func&amp;lt;T, string&amp;gt; itemContent)
    {
        var children = childrenProperty(root);
        if(children.Count() == 0)
        {
            sb.AppendLine("&amp;lt;/li&amp;gt;");
            return;
        }

        sb.AppendLine("\r\n&amp;lt;ul&amp;gt;");
        foreach (T item in children)
        {
            RenderLi(sb, item, itemContent);
            AppendChildren(sb, item, childrenProperty, itemContent);
        }

        sb.AppendLine("&amp;lt;/ul&amp;gt;&amp;lt;/li&amp;gt;");
    }

    private static void RenderLi&amp;lt;T&amp;gt;(StringBuilder sb, T item, Func&amp;lt;T, string&amp;gt; itemContent)
    {
        sb.AppendFormat("&amp;lt;li&amp;gt;{0}", itemContent(item));            
    }
}

&lt;/pre&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:87bf7f76-d6a6-49b4-b816-21114c5be587" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/ASPNET+MVC"&gt;ASPNET MVC&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/jQuery"&gt;jQuery&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/15.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/S7s_omvvvs4" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/02/08/asp.net-mvc-recursive-treeview-helper.aspx</guid>
            <pubDate>Sun, 08 Feb 2009 12:57:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/15.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/02/08/asp.net-mvc-recursive-treeview-helper.aspx#feedback</comments>
            <slash:comments>23</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/15.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/15.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/02/08/asp.net-mvc-recursive-treeview-helper.aspx</feedburner:origLink></item>
        <item>
            <title>jQuery UI 1.6rc6 tabs bug with IE6/7</title>
            <category>JavaScript</category>
            <category>Web Standards</category>
            <category>jQuery</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/hod2SayAexc/jquery-ui-1.6rc6-tabs-bug-with-ie67.aspx</link>
            <description>&lt;p&gt;I encountered a rather frustrating problem with jQuery UI tabs this week. The problem occurs when trying to tabify some content after using jQuery’s $().load method to load the tabs HTML via an ajax request.&lt;/p&gt;
&lt;p&gt;The following code works perfectly in all browsers except IE6 and IE7 (It works fine in IE8 as well), as can be seen in the screenshot below.&lt;/p&gt;
&lt;pre class="brush: js"&gt;$('#deviceDetailsWrapper').load('/device/details/294', null, function() {
    $('#tabs').tabs();
});
&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/jQueryUI1.6rc6tabsbugwithIE67_12D90/image.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="551" height="243" src="http://blog2.matthidinger.com/ContentImages/jQueryUI1.6rc6tabsbugwithIE67_12D90/image_thumb.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;However, here is what renders in IE6/7. For some reason, the jQuery tabs are triggering a GET request of the current URL and loading the content into the tab itself. Below you are actually seeing the entire page loaded inside the tab. I discovered this by inspecting the DOM tree within the tab in Firebug, as well as loading up Fiddler and watching the tab call an entirely separate GET request to the current URL as soon as the tabs were loaded. Strange behavior to me, since I am not entirely familiar with the jQuery tabs.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/jQueryUI1.6rc6tabsbugwithIE67_12D90/image_3.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="image" border="0" alt="image" width="579" height="425" src="http://blog2.matthidinger.com/ContentImages/jQueryUI1.6rc6tabsbugwithIE67_12D90/image_thumb_3.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;The Solution&lt;/h3&gt;
&lt;p&gt;The only thing I discovered was different regarding the .tabs() DOM manipulation in the different browsers was the ID of the tab – instead of being the #tab-id that I named it, the element was being assigned the full URL+#id to the container. So “#tab1” was becoming “http://localhost/device#tab1” – which I believe was triggering the tabs to behave in their “ajax” mode, which is a built-in feature of the jQuery tabs.&lt;/p&gt;
&lt;p&gt;The solution I found was opening up jquery.ui.all.js and locating the following code:&lt;/p&gt;
&lt;pre class="brush: js"&gt;this.$tabs.each(function(i, a) {
var href = $(a).attr('href');

// inline tab
if (fragmentId.test(href))
    self.$panels = self.$panels.add(self._sanitizeSelector(href));
&lt;/pre&gt;

Replace it with the following: 

&lt;pre class="brush: js"&gt;
this.$tabs.each(function(i, a) {
var href = $(a).attr('href');
            
// Fix tab IDs in IE6/7
href = href.substring(href.indexOf("#"));

// inline tab
if (fragmentId.test(href))
    self.$panels = self.$panels.add(self._sanitizeSelector(href)); 
&lt;/pre&gt;
&lt;p&gt;Hopefully this helps someone in their googling of this problem. I will be logging this as a bug with the jQuery developers.&lt;/p&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:78c01e1c-bb37-4e37-946f-1cd5008cfe76" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/javascript"&gt;javascript&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/jQuery"&gt;jQuery&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/web+standards"&gt;web standards&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/14.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/hod2SayAexc" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/02/07/jquery-ui-1.6rc6-tabs-bug-with-ie67.aspx</guid>
            <pubDate>Sat, 07 Feb 2009 12:53:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/14.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/02/07/jquery-ui-1.6rc6-tabs-bug-with-ie67.aspx#feedback</comments>
            <slash:comments>10</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/14.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/14.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/02/07/jquery-ui-1.6rc6-tabs-bug-with-ie67.aspx</feedburner:origLink></item>
        <item>
            <title>LINQ Audit Trail v2 - DoddleAudit</title>
            <category>LINQ</category>
            <category>LINQ to SQL</category>
            <category>Doddle</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/XEVnGgHRgIM/linq-audit-trail-v2.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://www.matthidinger.com/archive/2008/05/08/linq-to-sql-audit-trail.aspx"&gt;A couple months ago&lt;/a&gt; I wrote a basic set of extension methods to handle automatic auditing in LINQ to SQL. Well I have received a large number of emails regarding this particular project so I have decided to focus on cleaning up my v2 API and releasing it on CodePlex. There was a lot of room for improvement from version 1 and today I am going to post the all new LINQ Audit Trail code. This new version is significantly enhanced in the previous version.&lt;/p&gt;  &lt;h3&gt;Objective&lt;/h3&gt;  &lt;blockquote&gt;Automatic auditing of all inserts/updates/deletes for any table in your database with a single line of code, including:    &lt;p /&gt;    &lt;ul&gt;     &lt;li&gt;What table was modified? &lt;/li&gt;      &lt;li&gt;What fields changed? &lt;/li&gt;      &lt;li&gt;Who made the change? &lt;/li&gt;      &lt;li&gt;When did it occur? &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;h3&gt;   &lt;br /&gt;Usage&lt;/h3&gt;  &lt;p&gt;Simply define your audit definitions at any time before calling SubmitChanges(); &lt;/p&gt;  &lt;pre class="brush: c#"&gt;this.Products.Audit();
this.Categories.Audit();
this.Orders.Audit().AuditAssociation(o =&amp;gt; o.Order_Details);
this.Contacts.Audit().AuditAssociation(c =&amp;gt; c.Addresses).AuditAssociation(c =&amp;gt; c.PhoneNumbers);&lt;/pre&gt;

&lt;br /&gt;

&lt;h3&gt;Updates and Download&lt;/h3&gt;

&lt;p&gt;Please see the CodePlex project for updates and new releases. &lt;strong&gt;&lt;a href="http://www.codeplex.com/DoddleAudit"&gt;DoddleAudit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;br /&gt;

&lt;h3&gt;New Features and Fixes in V2&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;A significantly refined API for defining which tables to audit, including automatic primary key lookups. &lt;/li&gt;

  &lt;li&gt;Inserted records will have their primary keys correctly stored in the audit table now. &lt;/li&gt;

  &lt;li&gt;Built-in support for auditing across relationships. 
    &lt;ul&gt;
      &lt;li&gt;E.g., assume you want to audit a Contacts table which has a 1-to-many relationship to the Addresses table, thus allowing any number of Addresses to each Contact. Well ideally you want to show these Address audits on your ContactDetails.aspx, which is exactly what you can see in the screenshot below.  &lt;br /&gt;&lt;a href="http://www.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image_thumb.png" width="535" height="508" /&gt;&lt;/a&gt; 

        &lt;br /&gt;

        &lt;br /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;li&gt;Ability to define custom “audit property resolvers” to override the default auditing mechanism for properties that you specify. 
  &lt;ul&gt;
    &lt;li&gt;For example, notice in the above screenshot that “Address Type” has a value of “1” since that is how the data is stored in the table. This number does little good for the end user, so in V2 it is now possible to customize specific properties as needed. I will explain more details about this soon. Below I am overriding the default auditing of the Product.CategoryID property by querying the category by looking up the CategoryID, returning the Category.CategoryName, and renaming the audit field to “Category” since “CategoryID” is no longer accurate. &lt;/li&gt;
  &lt;/ul&gt;

  &lt;pre class="brush: c#"&gt;public class ProductAuditResolver : AuditPropertyResolver&lt;product&gt;
{
    protected override void CustomizeProperties()
    {
        CustomizeProperty(p =&amp;gt; p.CategoryID, categoryId =&amp;gt; GetCategoryByID(cid).CategoryName, "Category");
    }
}	
   &lt;/product&gt;&lt;/pre&gt;

  &lt;p /&gt;

  &lt;h3&gt;
    &lt;br /&gt;&lt;/h3&gt;

  &lt;h3&gt;Instructions&lt;/h3&gt;

  &lt;ol&gt;
    &lt;li&gt;&lt;a href="http://www.codeplex.com/doddleaudit" target="_blank"&gt;Download the latest release from CodePlex&lt;/a&gt;, the source code and compiled DLL are available, and add reference to &lt;strong&gt;Doddle.Linq.Audit.dll&lt;/strong&gt; in your project that contains your LINQ to SQL DBML &lt;/li&gt;

    &lt;li&gt;At a minimum you will need to add 2 tables to your database (and your DBML) to store the audit records. Please see the schema below and add these tables to your database. 
      &lt;ul&gt;
        &lt;li&gt;NOTE: Keep in mind this database schema is entirely customizable. I chose to use two tables to store all of my audits, but you could very easily change this logic to use a separate table for each entity or whatever storage schema you choose.   &lt;br /&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image_thumb_3.png" width="709" height="274" /&gt;&lt;/a&gt; 

          &lt;br /&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;Open your DBML and click in the designer surface. In the property pane you will need to change the &lt;strong&gt;Base Class&lt;/strong&gt; property of your generated DataContext to be &lt;strong&gt;Doddle.Linq.Audit.LinqToSql.AuditableDataContext  &lt;br /&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQAuditTrailv2_B491/image_thumb_4.png" width="618" height="243" /&gt;&lt;/a&gt; 

        &lt;br /&gt;

        &lt;br /&gt;&lt;/strong&gt;&lt;/li&gt;

    &lt;li&gt;Lastly you will need to create a partial DataContext class to wire up the auditing infrastructure to match your database schema. Add a new Class file to your project and insert the following code. Customize if necessary to match your auditing schema. 
      &lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

      &lt;pre class="brush: c#"&gt;public partial class NorthwindEntitiesDataContext
{
    protected override void InsertAuditRecordToDatabase(EntityAuditRecord record)
    {
        AuditRecord audit = new AuditRecord();
        audit.Action = (byte)record.Action;
        audit.AuditDate = DateTime.Now;
        audit.AssociationTable = record.AssociationTable;
        audit.AssociationTableKey = record.AssociationTableKey;
        audit.EntityTable = record.EntityTable;
        audit.EntityTableKey = record.EntityTableKey;

        audit.UserName = HttpContext.Current.User.Identity.Name;

        foreach (ModifiedEntityProperty av in record.ModifiedProperties)
        {
            AuditRecordModifiedField field = new AuditRecordModifiedField();
            field.MemberName = av.MemberName;
            field.OldValue = av.OldValue;
            field.NewValue = av.NewValue;

            audit.AuditRecordModifiedFields.Add(field);
        }

        this.AuditRecords.InsertOnSubmit(audit);
    }

    protected override void DefaultAuditDefinitions()
    {
        this.Products.Audit();
        this.Categories.Audit().AuditAssociation(c =&amp;gt; c.Products);
    }
}&lt;/pre&gt;
    &lt;/li&gt;
  &lt;/ol&gt;

  &lt;h3&gt;Known Issues&lt;/h3&gt;

  &lt;ol&gt;
    &lt;li&gt;I have not finished the support for the Entity Framework implementation of the auditing yet. If anyone more experienced with EF is out there downloading this source please let me know if you want to help complete it. 
      &lt;br /&gt;&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;Hopefully that is enough to get anyone started with the code. I am certainly looking for feedback for any suggestions, problems, or improvements. After some more unit testing and perhaps some slight refinements to the API I will remove the “beta” moniker.&lt;/p&gt;

  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:0e930095-434d-4e67-a764-90f4af23f0d9" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/LINQ" rel="tag"&gt;LINQ&lt;/a&gt;,&lt;a href="http://technorati.com/tags/LINQ+to+SQL" rel="tag"&gt;LINQ to SQL&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Doddle" rel="tag"&gt;Doddle&lt;/a&gt;&lt;/div&gt;

  &lt;p /&gt;
&lt;/li&gt;&lt;img src="http://www.matthidinger.com/aggbug/13.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/XEVnGgHRgIM" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2009/01/12/linq-audit-trail-v2.aspx</guid>
            <pubDate>Mon, 12 Jan 2009 12:50:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/13.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2009/01/12/linq-audit-trail-v2.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/13.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/13.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2009/01/12/linq-audit-trail-v2.aspx</feedburner:origLink></item>
        <item>
            <title>Fixing Web Application Projects with automated TFS Builds</title>
            <category>ASP.NET</category>
            <category>TFS</category>
            <category>CI</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/SLGi1uQ9pz4/fixing-web-application-projects-with-automated-tfs-builds.aspx</link>
            <description>&lt;p&gt;This weekend I started playing with Automated Builds in TFS 2008. Over the next few weeks I am going to setup automated builds for my various projects so I can start running automated integration testing and automated staging releases at certain intervals (nightly, weekly, etc). Unfortunately I hit a snag when I tried building one of my solutions that contained a Web Application Project.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_thumb.png" width="474" height="247" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After some digging around, I eventually opened up the “Release.txt” log file which can be found in the deployment directory, I found the following error:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;error MSB4019: The imported project "C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the &amp;lt;Import&amp;gt; declaration is correct, and that the file exists on disk.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now I am no where near an expert on MSBuild or the delicacies of .csproj files, so I did my best to poke around in there and see what might be going on. For those unaware, every .csproj file is actually just an XML file with various details about your actual project. In order to view/edit the project definition you can simply right-click on the project and select “Unload Project.” Once it has been unloaded, you can right-click again and select “Edit YourProject.csproj”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_thumb_3.png" width="117" height="245" /&gt;&lt;/a&gt;  &lt;a href="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_thumb_4.png" width="244" height="147" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once open, a search for the &amp;lt;Import&amp;gt; tag revealed the exact line causing the problem.&lt;/p&gt;    &lt;pre class="brush: xml"&gt;
&amp;lt;Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" /&amp;gt;
&lt;/pre&gt;

&lt;p&gt;It would appear the Visual Studio 2008 will install all necessary MSBuild targets into the v9.0 directory – which is exactly what brings us to our problem. My Build Server does not have Visual Studio installed, it is just a basic Server 2008 box with .NET 3.5 and nothing fancy (aside from all the TFS gear). The problem is that these v9.0 targets were not available on my build machine, so I found 2 completely different solutions that ended up resolving my issue.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Solution 1 – Add Conditional Imports (Not Recommended)&lt;/h3&gt;

&lt;p&gt;A google search of the actual MSBuild error brought me to a single post by &lt;a href="http://stevenharman.net/blog/archive/0001/01/01/multi-targeting-vs2005-and-vs2008-web-application-projects-a-gotcha.aspx"&gt;Steven Harman&lt;/a&gt; which seemed helpful but I was skeptical because it was related to multi-targeting and problems with a machine running both VS 2008 and VS 2005. I decided to try it out by editing my csproj to the following:&lt;/p&gt;

&lt;p&gt;I replaced the original &amp;lt;Import&amp;gt; declaration to the following&lt;/p&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;ImportCondition="'$(Solutions.VSVersion)' == '8.0'" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\WebApplications\Microsoft.WebApplication.targets" /&amp;gt;

&amp;lt;ImportCondition="'$(Solutions.VSVersion)' == '9.0'" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" /&amp;gt;
&lt;/pre&gt;

&lt;p&gt;With this change in place, I re-ran by TFS Build and it worked successfully. Unfortunately, this is extremely tedious to manually edit all of my .csproj files to facilitate automated builds. &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Solution 2 – Copy the v9.0 Targets to Build Machine (Recommended)&lt;/h3&gt;

&lt;p&gt;Once I started really thinking about the error, another solution seemed very clear and simple – just provide my build server with the target files. This solution ends up being much simpler and does not require editing any csproj files:&lt;/p&gt;

&lt;p&gt;On your development machine, copy everything in “C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0”  to the same folder on your build machine. This will provide your build machine with the correct target files required by your projects. I have only tested the Web Application projects but I see no reason that everything else would not work properly. Please let me know if anyone runs into issues with this.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/FixingWebApplicationProjectswithautomate_B396/image_thumb_5.png" width="695" height="386" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7de6d328-ebfc-403f-8e09-4ca073c5b0d5" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/ASPNET" rel="tag"&gt;ASPNET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/TFS" rel="tag"&gt;TFS&lt;/a&gt;,&lt;a href="http://technorati.com/tags/CI" rel="tag"&gt;CI&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASPNET+MVC" rel="tag"&gt;ASPNET MVC&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/12.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/SLGi1uQ9pz4" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/11/09/fixing-web-application-projects-with-automated-tfs-builds.aspx</guid>
            <pubDate>Sun, 09 Nov 2008 12:45:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/12.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/11/09/fixing-web-application-projects-with-automated-tfs-builds.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/12.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/12.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/11/09/fixing-web-application-projects-with-automated-tfs-builds.aspx</feedburner:origLink></item>
        <item>
            <title>Increase AddIn Performance with MAF and WPF using LoaderOptimization</title>
            <category>WPF</category>
            <category>MAF</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/a5UAplo112w/increase-addin-performance-with-maf-and-wpf-using-loaderoptimization.aspx</link>
            <description>&lt;p&gt;As mentioned in my &lt;a href="http://blog2.matthidinger.com/archive/2008/10/12/managed-addin-framework-system.addin-with-wpf.aspx"&gt;previous article&lt;/a&gt;, the &lt;a href="http://www.codeplex.com/clraddins"&gt;Managed AddIn Framework&lt;/a&gt; supports AppDomain isolation out of the box. This can come in very handy as long as you understand what is really happening under the covers. I am not going to cover all the details of AppDomain isolation and assembly loading within the CLR, but there are plenty of great resources about such things on MSDN. All you need to know for this article is that every .NET assembly much be loaded into memory within an AppDomain, and unless you specifically share assemblies across these domains (as explained below) then they will be loaded into memory for every AppDomain you create. This is particularly important for WPF AddIns, because the WPF assemblies consume a rather generous portion of memory, and since your AddIns are each loaded into their own AppDomain, this means that the WPF assemblies must &lt;em&gt;also&lt;/em&gt; be loaded into each of these AppDomains. If you are not careful, your application could begin to consume large amounts of memory without you even noticing.&lt;/p&gt;  &lt;p&gt;To solve this, you can place an attribute on the Main method of any .NET executable, explicitly stating that you want the CLR to share any assemblies that it can. There are certain rules for an assembly to be shareable, one of which is that it must have a strong name and be placed in the GAC – obviously this is not a problem for the .NET framework assemblies, WPF in our case.&lt;/p&gt;  &lt;p&gt;When you create a new WPF Project the project template will create an App.xaml for you. Since WPF does a little magic behind the scenes, there is no way to access the Main method of your application. In this case, you simply delete the App.xaml and create a new Application.cs class with the following code:&lt;/p&gt;  &lt;pre class="brush: c#; highlight: [12];"&gt;

public class Application : System.Windows.Application
{
    public Application()
    {
        StartupUri = new Uri("Window1.xaml", UriKind.Relative);
    }
    
    public static Application App;

    [System.STAThreadAttribute()]
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [System.LoaderOptimization(LoaderOptimization.MultiDomainHost)]
    public static void Main()
    {
        // Add attribute above this method
        Application app = new Application();
        App = app;
        app.Run();
    }
}
&lt;/pre&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:34b2da25-476c-4537-b194-f29e24cf66a1" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/MAF" rel="tag"&gt;MAF&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/11.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/a5UAplo112w" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/10/12/increase-addin-performance-with-maf-and-wpf-using-loaderoptimization.aspx</guid>
            <pubDate>Sun, 12 Oct 2008 11:39:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/11.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/10/12/increase-addin-performance-with-maf-and-wpf-using-loaderoptimization.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/11.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/11.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/10/12/increase-addin-performance-with-maf-and-wpf-using-loaderoptimization.aspx</feedburner:origLink></item>
        <item>
            <title>Managed AddIn Framework (System.AddIn) with WPF</title>
            <category>MAF</category>
            <category>WPF</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/aDuIVMF6lHc/managed-addin-framework-system.addin-with-wpf.aspx</link>
            <description>&lt;p&gt;Disclaimer: This post is mainly for my own reference. Quite honestly, the Managed AddIn Framework (henceforth known as MAF), is a rather complex beast, and I simply cannot remember all the steps necessary to utilize it properly without a small reference guide. This post will cover the complete step-by-step tutorial of every action that a developer must perform to utilize the AddIn framework. It will not be a complete overview of what MAF is or how all the parts tie together. I will do my best to cover these things, but I have also included some very helpful reference material that will cover these topics better than I ever could.&lt;/p&gt;  &lt;h3&gt;Before continuing&lt;/h3&gt;  &lt;p&gt;This post does not cover all the intricacies and overall design of the Managed AddIn framework. While it will in fact walk you through a step-by-step creation of a WPF app that supports AddIns, it will not fully explain what the various MAF pipeline projects are used for (or the pipeline itself for that matter). It would be in your best interest to watch this excellent screencast from Daniel Roth first.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://channel9.msdn.com/posts/DanielMoth/Managed-AddIn-Framework/"&gt;Daniel Roth 18 min screencast&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/bb384200.aspx" href="http://msdn.microsoft.com/en-us/library/bb384200.aspx"&gt;Excellent MSDN coverage of MAF&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;What is it?&lt;/h3&gt;  &lt;p&gt;MAF is the (much overdue, in my opinion) plugin/addin framework for .NET applications. It allows application developers to expose very simple extensibility points that allows third party developers to enhance your product. Common examples are creating an email client and relying on AddIns for services like Spell Checking, Virus Scanning, etc. Whether plugins are a core part of your application or merely a small feature, the Managed AddIn Framework should be employed to your advantage from here on out.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Note: System.AddIn is a .NET 3.5 assembly, and as such means that you must target .NETFX 3.5 to utilize it.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb.png" width="446" height="129" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;MAF consists of the following assemblies&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;System.AddIn &lt;/li&gt;    &lt;li&gt;System.AddIn.Contract &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;MAF gives your application the following benefits (at the expense of extra complexity and a steeper learning curve)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Discovery&lt;/strong&gt; – Find addins at runtime &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Activation&lt;/strong&gt; – Load an addin at runtime &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Versioning&lt;/strong&gt; - Backwards/forward compatibility &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Isolation&lt;/strong&gt; – Load addins into separate AppDomains/Processes so they cannot crash they whole app, among other reasons &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Lifetime&lt;/strong&gt; &lt;strong&gt;Management&lt;/strong&gt; – MAF will handle addin lifetimes and memory/AppDomain management &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Sandboxing&lt;/strong&gt; – Load addins with specific permission sets like “Internet” &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Unloading&lt;/strong&gt; – Unload an addin without worrying about tedious AppDomain management &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Our goal&lt;/h3&gt;  &lt;p&gt;By the end of this article you should be able to produce something like below. I know it doesn’t look like much, but it’s tackling a very specific scenario for a hobby project I am working on currently. The goal is to create a host WPF app that allows me (or third parties) to write addins for the host that will render custom WPF UI and allow interaction with the rest of the application.&lt;/p&gt;  &lt;p&gt;Below we have a very basic WPF window with a TabControl. The cool thing about this application is that the TabControl is databound to an AddIn collection -- the tabs themselves as well as the tab content are entirely rendered at runtime from an AddIn via the Managed AddIn framework.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_3.png" width="305" height="306" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Step 1 – Define Contact Interface and utilize Pipeline Builder&lt;/h3&gt;  &lt;p&gt;The first thing you need to be (painfully) aware of, is the project/directory structure that the MAF Pipeline requires. There is some flexibility here but not a whole lot of wiggle room. Thankfully, the only project I have to concern myself with is the Contract assembly (CouchPotato.AddIn.Contract below). With a proper directory structure in place you can use a tool that the MAF team released called &lt;a href="http://www.codeplex.com/clraddins/Release/ProjectReleases.aspx?ReleaseId=9222"&gt;Pipeline Builder&lt;/a&gt; to generate the necessary MAF projects for you automatically. The arrows below indicate which projects were generated by Pipeline Builder – &lt;strong&gt;it is important to understand that the only project/code I actually wrote in this entire solution is the ICouchPotatoAddInContract.cs.&lt;/strong&gt; Please see the screencast above or the resources below for more details on Pipeline Builder.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_4.png" width="619" height="241" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ok let’s get started. The following instructions will create the optimal directory/project structure for a MAF-based application.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Prepare the directory structure for your MAF application by creating a parent folder in your Visual Studio 2008\Projects folder (or wherever you choose). I named my folder “CouchPotato” &lt;/li&gt;    &lt;li&gt;Next, create a new Class Library project for your AddIn contact, I chose CouchPotato.AddIn.Contract. Create this project inside your parent folder from Step 1.      &lt;ul&gt;       &lt;li&gt;Add reference to System.AddIn and System.AddIn.Contract &lt;/li&gt;        &lt;li&gt;Hopefully you have installed Pipeline Builder by now, so you should add reference to “C:\Program Files\Microsoft\Visual Studio Pipeline Builder\PipelineHints.dll”          &lt;ul&gt;           &lt;li&gt;&lt;em&gt;This assembly does not need to be deployed with your application. It is only used by the Pipeline Builder during debugging&lt;/em&gt; &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;Create your contract interface, I chose the following &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;    &lt;pre class="brush: c#"&gt;
[AddInContract]
public interface ICouchPotatoAddInContract : IContract
{
    string Name { get; }
    string Description { get; }
    void Initialize();
    INativeHandleContract HomeScreen { get; }
}
&lt;/pre&gt;

&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;For now, don’t worry about INativeHandleContract. This is an interface that the MAF team added to support much better UI passing between isolation boundaries (AppDomains). This interface allows an AddIn to very easily pass direct UI elements to the host application, which is very important for my application. &lt;/li&gt;

    &lt;li&gt;Notice that MAF requires two rules for your AddIn Contracts: first you must derive from the &lt;strong&gt;IContact&lt;/strong&gt; interface from System.AddIn.Contract assembly, as well as add the &lt;strong&gt;[AddInContract]&lt;/strong&gt; attribute also from the same assembly. &lt;/li&gt;

    &lt;li&gt;Next, I chose to specify some naming ‘hints’ to the Pipeline builder. These hints tell the Pipeline Builder utility what to name the 4 assemblies that it will be generating for me. Click here to view &lt;a href="http://www.codeplex.com/clraddins/Wiki/View.aspx?title=Using%20PipelineHints%20to%20Customize%20Output&amp;amp;referringTitle=Pipeline%20Builder"&gt;all available Pipeline Hints&lt;/a&gt; &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;pre class="brush: c#"&gt;
[assembly: PipelineHints.SegmentAssemblyName(PipelineHints.PipelineSegment.HostView, "CouchPotato.AddIn.HostView")]
[assembly: PipelineHints.SegmentAssemblyName(PipelineHints.PipelineSegment.AddInView, "CouchPotato.AddIn.AddInView")]
[assembly: PipelineHints.SegmentAssemblyName(PipelineHints.PipelineSegment.HostSideAdapter, "CouchPotato.AddIn.HostSideAdapters")]
[assembly: PipelineHints.SegmentAssemblyName(PipelineHints.PipelineSegment.AddInSideAdapter, "CouchPotato.AddIn.AddInSideAdapters")]
&lt;/pre&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;We are almost done, but before we build this project we need to change to output path from the default “/bin/Debug” to “../output/Contracts”. For further explanation on this please see the &lt;a href="http://channel9.msdn.com/posts/DanielMoth/Managed-AddIn-Framework/"&gt;excellent screencast by Daniel Moth&lt;/a&gt;. &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_5.png" width="633" height="124" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;Ok we are ready to build, go ahead and &lt;strong&gt;build your project&lt;/strong&gt;. 

      &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;This step is important because the Pipeline builder does not examine your source code to generate the dependent assemblies, only the compiled code via reflection.&lt;/em&gt; &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;Launch the Pipeline Builder from the Tools menu. Default settings should be fine if you have been following along. Pressing OK should generate 4 new projects to your solution, as seen above. &lt;/li&gt;

    &lt;li&gt;&lt;em&gt;Note: &lt;/em&gt;I believe this is a bug I ran into with the Pipeline Builder CTP, but in my case I was forced to rename the generated Assembly Name/Default Namespace after the first generation as seen below. Take a look at your projects and verify these settings. Once you change them the first time you will not have to do it again, even if you use Pipeline builder again (and you will). &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_6.png" width="767" height="124" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt; &lt;/h3&gt;

&lt;h3&gt;Step 2 – Create our Host WPF Application&lt;/h3&gt;

&lt;p&gt;Now that our AddIn Pipeline is complete let’s create the host application. &lt;/p&gt;

&lt;p /&gt;

&lt;p&gt;Open a new instance of Visual Studio and create a new WPF Project, create it inside the same parent folder that we used for our Contracts project. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Add reference to System.AddIn &lt;/li&gt;

  &lt;li&gt;Add reference to your HostView assembly that can be found by browsing to “../output/CouchPotato.AddIn.HostView.dll” &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;Important: &lt;/em&gt;Make sure you set &lt;strong&gt;CopyLocal=false&lt;/strong&gt; for your HostView assembly &lt;/li&gt;
&lt;/ul&gt;

&lt;p /&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_7.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_7.png" width="775" height="467" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Finally, change your build output path to the root output directory &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_8.png" width="635" height="129" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I have created a very simple WPF Window with a TabControl. As you can see I am taking advantage of the ContentPresenter control to handle rending of the AddIn control for me. This is a great trick &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;TabControl x:Name="PluginContainer" TabStripPlacement="Bottom"&amp;gt;
    &amp;lt;TabControl.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;StackPanel&amp;gt;
                &amp;lt;TextBlock Text="{Binding Name}" /&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/TabControl.ItemTemplate&amp;gt;
    &amp;lt;TabControl.ContentTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;Grid&amp;gt;
                &amp;lt;ContentPresenter Content="{Binding HomeScreen}" /&amp;gt;
            &amp;lt;/Grid&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/TabControl.ContentTemplate&amp;gt;
&amp;lt;/TabControl&amp;gt;
&lt;/pre&gt;

&lt;ul&gt;
  &lt;li&gt;That is the last of our host configuration. Last thing we need to do is Update our AddInStore and load some AddIns &lt;em&gt;(unfortunately, we don’t have any yet, please see Step 3 :)&lt;/em&gt;  &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush: c#"&gt;
public Window1()
{
    InitializeComponent();

    AddInStore.Update(PipelineStoreLocation.ApplicationBase);
    Collection&amp;lt;AddInToken&amp;gt; addinTokens = AddInStore.FindAddIns(typeof(ICouchPotatoAddIn), PipelineStoreLocation.ApplicationBase);

    ObservableCollection&amp;lt;ICouchPotatoAddIn&amp;gt; addins = new ObservableCollection&amp;lt;ICouchPotatoAddIn&amp;gt;();
    foreach (AddInToken addinToken in addinTokens)
    {
        ICouchPotatoAddIn addin = addinToken.Activate&amp;lt;ICouchPotatoAddIn&amp;gt;(AddInSecurityLevel.Internet);
        addins.Add(addin);
    }
    
    PluginContainer.ItemsSource = addins;
}
&lt;/pre&gt;


&lt;h3&gt; &lt;/h3&gt;

&lt;h3&gt;Step 3 – Create our first AddIn&lt;/h3&gt;

&lt;p&gt;For this last step we are going to create a fake PhotoGallery AddIn.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open a new instance of Visual Studio and create a new Class Library project, create it inside the same parent folder that we used for our Contracts project. 
    &lt;ul&gt;
      &lt;li&gt;Add reference System.AddIn &lt;/li&gt;

      &lt;li&gt;If this is a WPF Addin, add reference PresentationFramework for FrameworkElement &lt;/li&gt;

      &lt;li&gt;Add reference to your AddInView assembly that can be found by browsing to “../output/AddInViews/AddInView.dll” &lt;/li&gt;

      &lt;li&gt;&lt;em&gt;Important: &lt;/em&gt;Make sure you set &lt;strong&gt;CopyLocal=false&lt;/strong&gt; for your &lt;strong&gt;AddInView&lt;/strong&gt; assembly &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_9.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_9.png" width="785" height="456" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Set the AddIn output to a &lt;strong&gt;specific directory within the output/AddIns folder&lt;/strong&gt;, for example: &lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;..\output\AddIns\&lt;strong&gt;&lt;em&gt;PhotoGalleryAddIn&lt;/em&gt;&lt;/strong&gt; &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_10.png" width="622" height="130" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Now that configuration is complete let’s create our UserControl that will represent the UI for the AddIn. Simply right-click on the project and Add New Item, select WPF User Control, add any UI that you choose. &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush: xml"&gt;
&amp;lt;UserControl x:Class="CouchPotato.PhotoGalleryAddIn.PhotoGalleryControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300"&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;TextBlock Text="Happy Photos!" /&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/UserControl&amp;gt;
&lt;/pre&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Lastly, create a the WeatherAddIn.cs file &lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Implement the ICouchPotatoAddIn interface &lt;/li&gt;

      &lt;li&gt;Add the [AddIn] attribute to describe the AddIn. &lt;/li&gt;

      &lt;li&gt;As you can see below, the Pipeline Builder has turned the INativeHandleContract interface into a FrameworkElement for us! This is very handy, as it will allow seamless calls from UI elements across AppDomains without us knowing anything about it! All we have to do is return any FrameworkElement to satisfy the contract, in this case, a WPF UserControl does in fact derive from FrameworkElement, as does just about anything in the WPF visual namespace. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush: c#"&gt;
[AddIn("Photo Gallery", Version = "1.0.0.0")]
public class PhotoGalleryAddin : ICouchPotatoAddIn
{
    private readonly PhotoGalleryControl _control;

    public PhotoGalleryAddin()
    {
        _control = new PhotoGalleryControl();
    }

    public string Name
    {
        get { return "Photo Gallery"; }
    }

    public string Description
    {
        get { return "View all your photos"; }
    }

    public void Initialize()
    {
    }

    public FrameworkElement HomeScreen
    {
        get { return _control; }
    }
}
&lt;/pre&gt;

&lt;h3&gt;Run it!&lt;/h3&gt;

&lt;p&gt;With any luck, hopefully you are able to run your host application and find the AddIn you created. There are a lot of working parts when you use the Managed AddIn Framework, and as such, there are many points of failure. As you can see there is a slight learning curve to utilize MAF but hopefully after this article and the Daniel Moth screencasts you should be pretty comfortable with the framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_11.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ManagedAddInFrameworkSystem.AddInwithWPF_B14E/image_thumb_11.png" width="713" height="551" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a title="http://channel9.msdn.com/posts/DanielMoth/Managed-AddIn-Framework/" href="http://channel9.msdn.com/posts/DanielMoth/Managed-AddIn-Framework/"&gt;Excellent Daniel Moth screencast on MAF&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a title="http://www.codeplex.com/clraddins" href="http://www.codeplex.com/clraddins"&gt;Managed AddIn Framework at CodePlex&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a title="http://www.codeplex.com/clraddins/Release/ProjectReleases.aspx?ReleaseId=9222" href="http://www.codeplex.com/clraddins/Release/ProjectReleases.aspx?ReleaseId=9222"&gt;Pipline Builder&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ddd9789c-b045-4d6d-a88a-d99e0e4214d6" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/MAF" rel="tag"&gt;MAF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/10.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/aDuIVMF6lHc" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/10/12/managed-addin-framework-system.addin-with-wpf.aspx</guid>
            <pubDate>Sun, 12 Oct 2008 11:36:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/10.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/10/12/managed-addin-framework-system.addin-with-wpf.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/10.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/10.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/10/12/managed-addin-framework-system.addin-with-wpf.aspx</feedburner:origLink></item>
        <item>
            <title>Code Snippets with Snippet Designer and ReSharper Live Templates</title>
            <category>Tools</category>
            <category>Visual Studio</category>
            <category>ReSharper</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/VzeRpBr685c/code-snippets-with-snippet-designer-and-resharper-live-templates.aspx</link>
            <description>&lt;h3&gt;Just what exactly are these snippets?&lt;/h3&gt;  &lt;p&gt;I believe that snippets are an underused feature built into Visual Studio. This post is my attempt at comparing the two tools I have used for snippet creation, and hoping to make more developers out there aware of just how easy they are to create and use in your existing projects. I am by no means an expert with either of these tools, but I think that is the point: &lt;em&gt;they take a few minutes to create and can be reused for immediate time savers.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Much to my surprise there exists a significant number of .NET developers that are not taking advantage of code snippets, built-in or otherwise. No doubt you have all seen them in intellisense before: they appear with a partially-jagged piece of paper as seen below. When selected, they expand into a template of code that has select editable variables. A number of predefined code-snippets ship with Visual Studio, many of which I use regularly, including ctor, prop, exception, try, etc.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb.png" width="313" height="219" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The “prop” snippet “expands” into the following code:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_3.png" width="292" height="27" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;So the big question is how can we create our own snippets? Let’s take a real-world example and find out.&lt;/p&gt;  &lt;h3&gt;Snipper Designer (free Visual Studio Plugin)&lt;/h3&gt;  &lt;p&gt;A few weeks ago a project was released on CodePlex called Snipper Designer. &lt;a href="http://www.codeplex.com/SnippetDesigner"&gt;Snippet Designer&lt;/a&gt;&lt;strong /&gt; is a plugin for Visual Studio that was previously used internally by Microsoft and has since been released for all of us to enjoy. After downloading the MSI, it istalled in no time and I was on my way to creating a basic snippet I wish I had created long ago. &lt;/p&gt;  &lt;p&gt;To start off I took some Configuration Property code that I had already written as the starting point for my snippet. Anyone who has done extensive configuration with the System.Configuration assembly should be very familiar with this code: it is a property declaration for automatic strongly-typed reading and writing to an XML attribute in your app.config. There are a number of similar code snippets I will be creating for various Configuration-related tasks, and I hope to update this post with my complete list of Configuration snippets shortly.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_4.png" width="715" height="222" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can see, the Snipper Designer has added a context menu item to export highlighted code as a snippet. In doing so, the code below was produced in my Snippet Designer:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_5.png" width="845" height="173" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;From here all I had to do was decide which “variables” would be available in my snippet. This is identifiable by the twin dollar signs ($) at the beginning and end of the variable. Finally, I assigned the snippet a shortcut, which is how we will invoke the snippet expansion in a code file. The shortcut I chose was “configProp.”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_6.png" width="243" height="243" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Our final bit of customization lies in a property pane below the snippet code. From here I can define tooltips to help other developers who may be using my snippets, as well as set default values and expected data types associated with a variable. As you can see, I specified that the isRequired variable should be a Boolean that defaults to true. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_7.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_7.png" width="1069" height="194" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;   &lt;br /&gt;ReSharper Live Templates&lt;/h3&gt;  &lt;p&gt;Many of you will probably be familiar with the Visual Studio plugin &lt;a href="http://www.jetbrains.com/resharper"&gt;ReSharper&lt;/a&gt;. ReSharper has quickly become a favorite of mine over the last year or so, and I feel as though I have only scratched the surface of it’s productivity potential. One of said features is their own snippet framework (which they have named Live Templates). ReSharper Live Templates are slightly more powerful than the aforementioned Snippet Designer. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_8.png" width="785" height="229" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can clearly see, the ReSharper snippet code is almost identical to Snippet Designer. This is a great thing. In fact, I copy-pasted my Snippet Designer code into ReSharper and it instantly recognized it, so the two are very interoperable in that regard. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_9.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_9.png" width="629" height="197" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The variable definition pane is where ReSharper really shines. It has significantly more customization over Snippet Designer, given it’s very nice macro support. I have certainly not experimented with all of these predefined macro’s but they seem like they would be great features for advanced and more intelligent snippet scenarios. I hope to play with them a bit more in the near future. Above you will notice that I have used the “Constant value” macro to specify defaults for the isRequired and DataType variable, which are “true” and “string”, respectively..&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_10.png" width="383" height="589" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;So what exactly did the last few minutes do for us? Well for me, any time in the future where I need to define a new Configuration Property in code, I will no longer by force into vastly error-prone copy-pasting. Instead, I simply trigger my snippet by it’s predefined shortcut. In my case, I chose “configProp.”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_11.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_11.png" width="271" height="212" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When selected, it expands into this simple code block, which allows me to [tab] through the 5 variables and be on my way. And if you happen to think this won’t save you much time, then I would challenge the fact that you have probably not copy-pasted a significant number of these configuration properties before. As I mentioned in the beginning, I will be creating an army of these snippets, ranging from not only my Configuration-related ones, but repeatable tasks like ViewState-backed property wrappers, etc.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/CodeSnippetswithSnippetDesignerandReShar_AE89/image_thumb_12.png" width="702" height="109" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Download&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.codeplex.com/SnippetDesigner"&gt;Snippet Designer&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.jetbrains.com/resharper"&gt;ReSharper&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4068c50c-239d-43d9-9139-f53a928416e0" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ReSharper" rel="tag"&gt;ReSharper&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/9.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/VzeRpBr685c" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/10/02/code-snippets-with-snippet-designer-and-resharper-live-templates.aspx</guid>
            <pubDate>Thu, 02 Oct 2008 11:24:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/9.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/10/02/code-snippets-with-snippet-designer-and-resharper-live-templates.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/9.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/9.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/10/02/code-snippets-with-snippet-designer-and-resharper-live-templates.aspx</feedburner:origLink></item>
        <item>
            <title>Synergy - 3 Desktops, 1 Keyboard</title>
            <category>Tools</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/G0MzQs_BNNE/synergy-3-desktops-1-keyboard.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/Synergy3Desktops1Keyboard_AC32/image_3.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://blog2.matthidinger.com/ContentImages/Synergy3Desktops1Keyboard_AC32/image_thumb_3.png" width="390" height="299" /&gt;&lt;/a&gt; I recently noticed a colleague of mine using a hardware KVM to share his desktop keyboard and mouse with his laptop. He had a standard hardware KVM with basic PS/2 inputs and could toggle between the PCs by pressing Scroll Lock twice. Pretty typical setup for many people who have multiple PCs, and it wasn't more than a few years ago that I was doing that same.&lt;/p&gt;  &lt;p&gt;Enter &lt;a href="http://synergy2.sourceforge.net/" target="_blank"&gt;Synergy&lt;/a&gt;. Synergy is actually lot more than a basic KVM. &lt;strong&gt;It makes multiple computers behave exactly as though they were a single PC with dual-monitors.&lt;/strong&gt; You simply move your mouse to the edge of one monitor and it instantly jumps to the next one -- even though they are entirely different computers. &lt;/p&gt;  &lt;p&gt;Synergy also lets you share your clipboard between all connected PCs, and it can even sync screensavers so they all start and stop together. But probably the best feature for some, is that Synergy works on Linux, Windows, and Mac! If you notice the screenshot to the right, I have a Fedora box on the far left. Oh, and did I mention it's open source and totally free?&lt;/p&gt;  &lt;p&gt;From the web site:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Synergy lets you easily share a single mouse and keyboard between multiple computers with different operating systems, each with its own display, without special hardware. It's intended for users with multiple computers on their desk since each system uses its own monitor(s). &lt;/p&gt;    &lt;p&gt;Redirecting the mouse and keyboard is as simple as moving the mouse off the edge of your screen. Synergy also merges the clipboards of all the systems into one, allowing cut-and-paste between systems. Furthermore, it synchronizes screen savers so they all start and stop together and, if screen locking is enabled, only one screen requires a password to unlock them all. &lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://www.matthidinger.com/aggbug/8.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/G0MzQs_BNNE" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/06/17/synergy-3-desktops-1-keyboard.aspx</guid>
            <pubDate>Tue, 17 Jun 2008 11:14:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/8.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/06/17/synergy-3-desktops-1-keyboard.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/8.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/8.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/06/17/synergy-3-desktops-1-keyboard.aspx</feedburner:origLink></item>
        <item>
            <title>LINQ to SQL Audit Trail</title>
            <category>LINQ</category>
            <category>C#</category>
            <category>LINQ to SQL</category>
            <category>Doddle</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/1XXOSYtdtJA/linq-to-sql-audit-trail.aspx</link>
            <description>&lt;h2 style="color: #800000"&gt;&lt;font color="#ff0000"&gt;UPDATE: This post is outdated and has significantly enhanced with a new version. Please see &lt;/font&gt;&lt;a href="http://blog.matthidinger.com/2009/01/12/LINQ+Audit+Trail+V2.aspx"&gt;&lt;font color="#ff0000"&gt;LINQ Audit Trail V2&lt;/font&gt;&lt;/a&gt; &lt;/h2&gt;  &lt;p&gt;In a project I am currently working on, we had a fairly common requirement of recording an Audit Trail of any data changes. The requirements were typical, provide a running log of any changes in the database, including:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;What table was modified? &lt;/li&gt;    &lt;li&gt;What fields changed? &lt;/li&gt;    &lt;li&gt;Who made the change? &lt;/li&gt;    &lt;li&gt;When did it occur? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Naturally, there are many ways to tackle this problem. In the past I have either relied on writing database Triggers for the tables, or wrote the Auditing logic right into the stored procedure that was doing the modification. But this time, since the project is utilizing LINQ to SQL, I had a more ambitious idea in mind. &lt;/p&gt;  &lt;h3&gt;The Goal&lt;/h3&gt;  &lt;p&gt;Create a flexible, and automated Auditing solution that would allow my team to add Audit tracking to any table in our database, with only a single line of C# code. &lt;/p&gt;  &lt;p&gt;The code I ended up with did in fact meet my goal -- which would add Auditing to the Products table and Categories table -- can be seen below.    &lt;br /&gt;As long as you call the Audit&amp;lt;&amp;gt; method before calling SubmitChanges() then any INSERTED/UPDATED/DELETED entities will be properly Audited automatically.     &lt;br /&gt;The first parameter in the method, is telling the Auditing code how to identity which property is the Primary Key of the table.&lt;/p&gt;  &lt;pre class="brush: c#"&gt;

public partial class NorthwindDataContext
{
    public override void SubmitChanges(ConflictMode failureMode)
    {
        this.Audit&amp;lt;Product&amp;gt;(p =&amp;gt; p.ProductID, "Product modified ");
        this.Audit&amp;lt;Category&amp;gt;(c =&amp;gt; c.CategoryID, "Category modified"); 
        base.SubmitChanges(failureMode);
    }
}

&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;TIP: If you are interested in learning how this code was created, then please feel free to read the rest of this article. If however, you are only interested in the finished product and using the code in your projects, then head down to the bottom :)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h3&gt;Step 1 - Database Tables&lt;/h3&gt;

&lt;p&gt;Given my requirements I derived the following database schema. For my purposes, these tables did the trick, but of course your requirements may differ slightly so you may tweak as you wish.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;strong&gt;Audits&lt;/strong&gt; table is used to track any change. Most of the columns should be self-explanatory. The Action is what CUD event occurred (Insert, Update, or Delete). The rest of the columns record who made the change, when, what table, and the Primary Key of the modified record. &lt;/li&gt;

  &lt;li&gt;The &lt;strong&gt;AuditValues&lt;/strong&gt; table is used to track each modified column in the table being audited: the Old (Original), and the New (Current) value. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb.png" width="439" height="585" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;Step 2 - The DBML&lt;/h3&gt;

&lt;p&gt;Now that we have our new tables, we will update our LINQ to SQL Entity classes. I am going to be using Northwind for this example.&lt;/p&gt;

&lt;p&gt; &lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb_3.png" width="484" height="845" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;Step 3 - The Public Audit Extension Method&lt;/h3&gt;

&lt;p&gt;First we need to create a public method that client code will use to begin Auditing a table.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
/// &amp;lt;summary&amp;gt;
/// This method will enlist a LINQ to SQL Entity for automatic Auditing
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name="TEntity"&amp;gt;The Entity class you want to audit changes on&amp;lt;/typeparam&amp;gt;
/// &amp;lt;param name="tableKeySelector"&amp;gt;A Lambda expression that will return the Primary Key of the Entity&amp;lt;/param&amp;gt;
/// &amp;lt;param name="title"&amp;gt;The text that will be logged in the audit table&amp;lt;/param&amp;gt;
public static void Audit&amp;lt;TEntity&amp;gt;(this DataContext db, Func&amp;lt;TEntity, int&amp;gt; tableKeySelector, string title) where TEntity : class
&lt;/pre&gt;

&lt;p&gt;This is our public entry point for Auditing a table. This method might look a little bit intimidating to those unfamiliar with generic classes and generic delegates. Let's dissect this method to make it a little more palatable.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The first thing you should be aware of, is that this is an Extenstion method to the DataContext class. This is clear when you notice the "this" keyword in the first parameter. That means that this method will be available on any DataContext in our project (assuming of course, that you import the namespace the extension class resides in). &lt;/li&gt;

  &lt;li&gt;The second thing that might look strange is the Func&amp;lt;T1, T2&amp;gt; generic parameter. This is actually a Generic Delegate that exists in the System.Core assembly that ships with 3.5.  The 5 Func&amp;lt;T1, T2, T3, T4, TResult&amp;gt; overloads are used to designate a method that operates on 1 or more inputs (T1 through T4) and returns a TResult. Func's can be seen all over the LINQ namespace and you will get probably pretty familiar with them once you being extending and using LINQ. Typically, they will define the signature for a Lambda expression (which is a new C# shorthand for defining an expression or anonymous method call). In this particular Func&amp;lt;&amp;gt; parameter, I am expecting a method (a Lambda expression, typically), that accepts a TEntity for input, and returns an int. This is required because we need to know how to find the Primary Key property of an Entity. &lt;/li&gt;

  &lt;li&gt;The third unique syntax in this method is the "where" keyword. This is telling the generic method that any TEntity that is passed to this method will be a reference type. This is required because LINQ to SQL can only map reference types. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Step 4 - Auditing LINQ to SQL Entity Inheritance&lt;/h3&gt;

&lt;p&gt;I ran into something unexpected when I began testing the auditing code I wrote: Auditing my Entities that used inheritance. In case you didn't know, LINQ to SQL supports a type of relational inheritance known as Table-Per-Class Hierarchy. This means that every custom field for the derived entity classes are stored in the same table in the database. This article will not go into this subject any further, but please see &lt;a title="http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/10/01/linq-to-sql-inheritance.aspx" href="http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/10/01/linq-to-sql-inheritance.aspx" target="_blank"&gt;Guy Burnstein's Inheritance Article&lt;/a&gt; on the subject of LINQ to SQL inheritance. The following images are courtesy of him, and only for demonstration's sake -- these entities will not be in my sample code.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" alt="Linq to SQL Inheritance" src="http://blogs.microsoft.co.il/blogs/bursteg/WindowsLiveWriter/LinqtoSQLInheritance_7597/Person_0f4a4940-612f-4ad6-9969-9d7eb8cdea18.jpg" width="357" height="457" /&gt;&lt;img border="0" alt="Linq to SQL Inheritance" src="http://blogs.microsoft.co.il/blogs/bursteg/WindowsLiveWriter/LinqtoSQLInheritance_7597/TablePerClassHierarchy_bb6bd854-6f96-44bb-9737-52680ec4f532.jpg" width="297" height="315" /&gt;&lt;/p&gt;

&lt;p&gt;Naturally, I assumed that I could use the following code to Audit entities that supported inheritance just like regular Entities:&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
this.Audit&amp;lt;SalesPerson&amp;gt;(sp =&amp;gt; sp.PersonID, "SalesPerson changed");
this.Audit&amp;lt;Contact&amp;gt;(c =&amp;gt; c.PersonID, "Contact changed");
&lt;/pre&gt;

&lt;p&gt;Unfortunately for me, I was wrong. The Auditing code that I wrote relies on dataContext.GetTable&amp;lt;TEntity&amp;gt; to obtain a reference to the table being audited -- however, when I tried doing dataContext.GetTable&amp;lt;SalesPerson&amp;gt; I received an unpleasant exception stating that a derived entity cannot be used with the GetTable method -- instead, the exception actually suggested that I try dataContext.GetTable&amp;lt;Person&amp;gt;(), which did indeed work.&lt;/p&gt;

&lt;p&gt;So due to this unexpected exception, I had to add an overload to the Audit method that supported two types, a TBaseEntity, and a TSubEntity.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
this.Audit&amp;lt;Contact, SalesPerson&amp;gt;(sp =&amp;gt; sp.PersonID, "SalesPerson changed");
&lt;/pre&gt;

&lt;p&gt;The method signature for this method is listed below. You will notice an additional Generic Constraint added, defining that TSubEntity must in fact derive from TBaseEntity.&lt;/p&gt;
&lt;pre class="brush: c#"&gt;
/// &amp;lt;summary&amp;gt;
/// This method will enlist a LINQ to SQL Entity for automatic Auditing
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name="TBaseEntity"&amp;gt;The Base Entity class you want to audit changes on&amp;lt;/typeparam&amp;gt;
/// &amp;lt;typeparam name="TSubEntity"&amp;gt;The Derived Entity class, for use in LINQ to SQL inheritance&amp;lt;/typeparam&amp;gt;
/// &amp;lt;param name="tableKeySelector"&amp;gt;A Lambda expression that will return the Primary Key of the Entity&amp;lt;/param&amp;gt;
/// &amp;lt;param name="title"&amp;gt;The text that will be logged in the audit table&amp;lt;/param&amp;gt;
public static void Audit&amp;lt;TBaseEntity, TSubEntity&amp;gt;(this DataContext db, Func&amp;lt;TSubEntity, int&amp;gt; tableKeySelector, string title)
       where TBaseEntity : class
       where TSubEntity : TBaseEntity
&lt;/pre&gt;

&lt;h3&gt;Step 5 - Auditing Inserted Records&lt;/h3&gt;

&lt;p&gt;The heart and soul of my auditing code relies on the DataContext's Object Tracking Service. You see, the LINQ to SQL DataContext is of course responsible for tracking entity changes. This is a necessary service so that it is able to queue up every insert, update, and delete -- patiently waiting for a call to dataContext.SubmitChanges(), at which point the context runs through every necessary SQL command to INSERT, UPDATE, and DELETE records in the database.&lt;/p&gt;

&lt;p&gt;Thankfully, the DataContext exposes a GetChangeSet() method, which will allow us to peek into its pending database calls.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb_4.png" width="377" height="159" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;pre class="brush: c#"&gt;
private static void AuditInserts&amp;lt;TEntity, TSubEntity&amp;gt;(DataContext db, Func&amp;lt;TSubEntity, int&amp;gt; tableKeySelector, string title)
    where TEntity : class
    where TSubEntity : TEntity
{
    var inserts = db.GetChangeSet().Inserts.OfType&amp;lt;TSubEntity&amp;gt;();
&lt;/pre&gt;

&lt;p&gt;Here we can see a perfect example of LINQ to Objects. The GetChangeSet().Inserts property return a List&amp;lt;Object&amp;gt;, but that doesn't do us much good, because we are only interested in the Entities we want to audit. Therefore, we can use the new OfType&amp;lt;&amp;gt; extension method to only pull back the entities we are concerned with.&lt;/p&gt;

&lt;p&gt;Next, we need to obtain a reference to the Table&amp;lt;&amp;gt; that our Entity belongs to.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
Table&amp;lt;TEntity&amp;gt; table = db.GetTable&amp;lt;TEntity&amp;gt;();
&lt;/pre&gt;

&lt;p&gt;Then we need to get all the public properties that our Entity has.&lt;/p&gt;


&lt;pre class="brush: c#"&gt;
PropertyInfo[] props = typeof(TSubEntity).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
&lt;/pre&gt;

&lt;p&gt;I have also created a quick helper-method that will create the row in the Audit table for us&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
private static Audit CreateAudit&amp;lt;TEntity&amp;gt;(string title, Table&amp;lt;TEntity&amp;gt; table, int key) where TEntity : class
{
    Audit audit = new Audit();
    audit.TableName = table.ToString();
    audit.TableKey = key;
    audit.UserName = CurrentUser;
    audit.AuditDate = DateTime.Now;
    return audit;
}
&lt;/pre&gt;

&lt;p&gt;The rest of the code is simply looping through all of the Entities in the ChangeSet. &lt;/p&gt;

&lt;pre class="brush: c#"&gt;
foreach (TSubEntity item in inserts)
{
    // Get the Primary Key for our table by Invoking the tableKeySelector delegate on the current TSubEntity item
    int key = tableKeySelector.Invoke(item);

    // Create the Audit
    Audit audit = CreateAudit&amp;lt;TEntity&amp;gt;(title, table, key);
    audit.Title = title + " added";
    audit.Action = "Insert";

    // Loop through every property in our inserted entity
    foreach (PropertyInfo pi in props)
    {
        // This code checks to see if the property is a LINQ to SQL column. You may change this if you need.
        if (pi.HasAttribute(typeof(ColumnAttribute)))
        {
            // I chose to ignore any Id columns in the auditing, again, you may change this
            if (pi.Name.EndsWith("Id"))
                continue;

            // Creat the AuditValue row and add it to our current Audit
            AuditValue values = new AuditValue();
            values.MemberName = pi.Name;
            values.NewValue = GetPropertyValue(pi, item);

            audit.AuditValues.Add(values);
        }
    }

    // Insert the Audit to the database
    db.InsertAudit(audit);
}
&lt;/pre&gt;

&lt;h3&gt;Step 6 - Audit Deletes&lt;/h3&gt;

&lt;p&gt;Very few things change from the Insert code here.&lt;/p&gt;
&lt;pre class="brush: c#"&gt;
var deletes = db.GetChangeSet().Deletes.OfType&amp;lt;TSubEntity&amp;gt;();
&lt;/pre&gt;
&lt;p&gt;I also set the OldValue property instead of the NewValue property when creating the AuditValues entity.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
AuditValue values = new AuditValue();
values.MemberName = pi.Name;
values.OldValue = GetPropertyValue(pi, item);
&lt;/pre&gt;

&lt;h3&gt;Step 7 - Audit Updates&lt;/h3&gt;

&lt;p&gt;Auditing updates is greatly simplified again thanks to our hard-working DataContext. Every Table&amp;lt;T&amp;gt; class has a GetModifiedMembers method that can be invoked on any entity. This method will only return properties which were CHANGED. This is exactly what I need because I did not want to record any values that stayed the same, especially for tables with a large number of columns.&lt;/p&gt;

&lt;pre class="brush: c#"&gt;
ModifiedMemberInfo[] mmi = table.GetModifiedMembers(item);
foreach (TSubEntity item in updates)
{
    int key = tableKey.Invoke(item);

    Audit audit = CreateAudit&amp;lt;TEntity&amp;gt;(title, table, key);
    audit.Title = title + " updated";
    audit.Action = "Update";

    ModifiedMemberInfo[] mmi = table.GetModifiedMembers(item);

    foreach (ModifiedMemberInfo mi in mmi)
    {
        AuditValue values = new AuditValue();
        values.MemberName = mi.Member.Name;

        values.OldValue = GetPropertyValue(mi.OriginalValue);
        values.NewValue = GetPropertyValue(mi.CurrentValue);

        audit.AuditValues.Add(values);
    }

    db.InsertAudit(audit);
}
&lt;/pre&gt;

&lt;h3&gt;The Finished Results&lt;/h3&gt;

&lt;p&gt;I wrote a very quick demo app for this article. You can see below a GridView of the Audits table rows. We can see what we changed, when, by whom, etc. If you select one of the Audits, a DetailsView will display all of the Changed Values that took place during the Audit.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb_5.png" width="694" height="211" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb_6.png" width="736" height="257" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_7.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/LINQtoSQLAuditTrail_7DCD/image_thumb_7.png" width="727" height="498" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;Get the Code!&lt;/h3&gt;

&lt;p&gt;If you stuck around for that whole article then I am impressed! If however, you just want to view, experiment with, and use the code, then I provide it here for your use. I have also included the sample Northwind Project so you can play with the demo yourself.&lt;/p&gt;

&lt;p&gt;To download the latest version of this project please see the CodePlex Project: &lt;a href="http://www.codeplex.com/DoddleAudit" target="_blank"&gt;DoddleAudit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, and please let me know if you end up using this code or have any cool features or optimizations that you have added or would like to see added! 
  &lt;br /&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3ac26440-e383-4f7a-9dbf-876ef1b13bc1" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/LINQ+to+SQL" rel="tag"&gt;LINQ to SQL&lt;/a&gt;,&lt;a href="http://technorati.com/tags/LINQ" rel="tag"&gt;LINQ&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Doddle" rel="tag"&gt;Doddle&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/7.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/1XXOSYtdtJA" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/05/08/linq-to-sql-audit-trail.aspx</guid>
            <pubDate>Thu, 08 May 2008 11:10:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/7.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/05/08/linq-to-sql-audit-trail.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/7.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/7.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/05/08/linq-to-sql-audit-trail.aspx</feedburner:origLink></item>
        <item>
            <title>IE6 Underscore Hack</title>
            <category>Web Standards</category>
            <category>CSS</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/LlBOv0phBGo/ie6-underscore-hack.aspx</link>
            <description>&lt;p&gt;So as you can see I've been playing with ASP.NET MVC in my free time lately. But as it turns out I learned something totally unrelated to MVC while I was editing the default stylesheet that MVC Preview 2 ships with.&lt;/p&gt;
&lt;pre class="brush: css"&gt;#mainContent
{
    padding: 30px 30px 15px 30px;
    background-color: #FFF;
    border-bottom: 3px groove #4b6f92;
    margin-bottom: 30px;
    _height: 1px; /* only IE6 applies CSS properties starting with an underscrore */
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;I can't believe I never knew about this. I have read 3 CSS books in the past few years and don't recall ever reading about this hack. So while it isn't the end-all solution to fixing CSS bugs in IE6, I think it should come in pretty handy in the future now that I know it exists.&lt;/p&gt;
&lt;p&gt;I found this URL to &lt;a title="http://www.wellstyled.com/css-underscore-hack.html" target="_blank" href="http://www.wellstyled.com/css-underscore-hack.html"&gt;WellStyled&lt;/a&gt; which describes the hack in more detail. Here are some cool usage examples of this hack:&lt;/p&gt;
&lt;pre class="brush: css"&gt;#box 
{ 
    min-height: 300px; 
    height: auto; 
    _height: 300px; 
}
#menu 
{ 
    position: fixed; 
    _position: absolute; 
}
&lt;/pre&gt;

&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:841dc355-39ad-4514-922c-24858f5af35a" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/CSS"&gt;CSS&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/web+standards"&gt;web standards&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/6.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/LlBOv0phBGo" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/05/07/ie6-underscore-hack.aspx</guid>
            <pubDate>Wed, 07 May 2008 11:01:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/6.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/05/07/ie6-underscore-hack.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/6.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/6.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/05/07/ie6-underscore-hack.aspx</feedburner:origLink></item>
        <item>
            <title>Entity Framework Comparison Frustration: Explained</title>
            <category>C#</category>
            <category>LINQ</category>
            <category>Entity Framework</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/Tw82KzUxPzY/entity-framework-comparison-frustration-explained.aspx</link>
            <description>&lt;p&gt;This post is a follow-up to an article I wrote a few weeks ago, &lt;a target="_blank" href="http://blog.matthidinger.com/2008/02/01/ADONETEntityFrameworkComparisonFrustration.aspx"&gt;ADO.NET Entity Framework Comparison Frustration&lt;/a&gt;. As a quick re-cap, I was simply trying to filter a list of users with a LINQ query expression by comparing custom classes, not primitive types.&lt;/p&gt;
&lt;pre class="brush: c#"&gt;TorvusEntities entities = new TorvusEntities(); 

// Pull my Account Entity from the database
Account matt = entities.Accounts.First(a =&amp;gt; a.AccountId == 10);

// Attempt to get all Teams by a Team Owner
var teams = from t in entities.Teams
                 where t.Owner == matt
                 select t;
&lt;/pre&gt;
&lt;p&gt;However, an exception was thrown. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unable to create a constant value of type 'Closure type'. Only primitive types (for instance Int32, String and Guid) are supported in this context.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So I left it at that. The Entity Framework could only handle comparison on primitive types, which makes sense of course, since the expression needs to be converted into the underlying data storage language (T-SQL in this case). I was simply hoping that they would provide a more object-oriented way of translating the comparison I hoped to express by some other means. E.g., overriding Object.Equals() or the == operator, implementing a certain interface on my entities, something that felt OO to me.&lt;/p&gt;
&lt;p&gt;Today however, I found my answer. Embarrassingly enough, it was &lt;a target="_blank" href="http://msdn2.microsoft.com/en-us/library/bb738686.aspx"&gt;in the MSDN docs all along&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A comparison expression checks whether a constant value, property value, or method result is equal, not equal, greater than, or less than another value. If a particular comparison is not valid for LINQ to Entities, an exception will be thrown. [Specifically, the exception I wrote above.] All comparisons, both implicit and explicit, require that all components are comparable in the data store. Comparison expressions are often used in &lt;strong&gt;Where&lt;/strong&gt; clauses for restricting the query results. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And here it is, the confirmation I wanted (albeit not the answer I was hoping for):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LINQ to Entities does not support using a user class as a constant. However, a property reference on a user class is considered a constant, and will be converted to a command tree constant expression and executed on the data store.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Oh, another thing worth mentioning, method returns don't count as so-called constant expressions, and will thrown an exception when attempted.&lt;/p&gt;
&lt;pre class="brush: c#"&gt;public class MyBusinessObject
{
    public int GetId()
    {
        return 5;
    }
}

public class Test
{
    public Test()
    {
        using (TorvusEntities context = new TorvusEntities())
        {
            MyBusinessObject myBo = new MyBusinessObject();
            var accounts = from a in context.Accounts
                           where a.AccountId == myBo.GetId()
                           select a;

            // Exception will be thrown at run-time,
            // methods do not count as Constant expressions
        }
    }
}
&lt;/pre&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:283bb60c-493f-48e3-97d4-2b34e173e875" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/Entity+Framework"&gt;Entity Framework&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/LINQ"&gt;LINQ&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/5.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/Tw82KzUxPzY" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/02/26/entity-framework-comparison-frustration-explained.aspx</guid>
            <pubDate>Tue, 26 Feb 2008 11:59:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/5.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/02/26/entity-framework-comparison-frustration-explained.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/5.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/5.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/02/26/entity-framework-comparison-frustration-explained.aspx</feedburner:origLink></item>
        <item>
            <title>Styles up Top, Scripts on Bottom</title>
            <category>ASP.NET</category>
            <category>JavaScript</category>
            <category>Web Standards</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/WH5dmGVd_x4/styles-up-top-scripts-on-bottom.aspx</link>
            <description>&lt;p&gt;Today I just stumbled onto some interesting information regarding placements of script blocks and CSS links. According to some extensive testing performed at Yahoo!, they have published a list of &lt;a title="http://developer.yahoo.com/performance/rules.html" target="_blank" href="http://developer.yahoo.com/performance/rules.html"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;. Many of these rules came as no surprise, for example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While researching performance at Yahoo!, we discovered that moving stylesheets to the document HEAD makes pages load faster. This is because putting stylesheets in the HEAD allows the page to render progressively. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, one rule caught my attention:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule 5 described how stylesheets near the bottom of the page prohibit progressive rendering, and how moving them to the document HEAD eliminates the problem. Scripts (external JavaScript files) pose a similar problem, but the solution is just the opposite: it's better to move scripts from the top to as low in the page as possible. One reason is to enable progressive rendering, but another is to achieve greater download parallelization. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So sure I thought, maybe it will provide better performance, but when creating internet-facing web sites I am a firm believer in standards and compliance. I admit I don't run my markup through an XHTML validator as much as I should, but I was always under the impression that for valid XHTML, &amp;lt;script&amp;gt; blocks and includes belong in the &amp;lt;head&amp;gt; element. Nay, according to the working &lt;a target="_blank" href="http://www.w3.org/TR/2003/WD-xhtml2-20030506/mod-scripting.html#edef_scripting_script"&gt;W3C XHTML Draft&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;a href="http://www.w3.org/mod-scripting.html#edef_scripting_script"&gt;script&lt;/a&gt; element places a script within a document. This element may appear any number of times in the &lt;a href="http://www.w3.org/mod-structure.html#edef_structure_head"&gt;head&lt;/a&gt; or &lt;a href="http://www.w3.org/mod-structure.html#edef_structure_body"&gt;body&lt;/a&gt; of an XHTML document.&lt;/p&gt;
&lt;/blockquote&gt;&lt;br /&gt;
&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4980c230-fa20-4baf-9dae-1782451fdf1a" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/javascript"&gt;javascript&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/web+standards"&gt;web standards&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/aspnet"&gt;aspnet&lt;/a&gt;&lt;a rel="tag" href="http://technorati.com/tags/css"&gt;css&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/4.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/WH5dmGVd_x4" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/02/25/styles-up-top-scripts-on-bottom.aspx</guid>
            <pubDate>Mon, 25 Feb 2008 11:52:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/4.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/02/25/styles-up-top-scripts-on-bottom.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/4.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/4.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/02/25/styles-up-top-scripts-on-bottom.aspx</feedburner:origLink></item>
        <item>
            <title>ASP.NET Debugging Tip</title>
            <category>ASP.NET</category>
            <category>Visual Studio</category>
            <link>http://feedproxy.google.com/~r/mhidinger/~3/zjh_X60W364/asp.net-debugging-tip.aspx</link>
            <description>&lt;p&gt;Honestly, I'm not sure if this setting is new to Visual Studio 2008 or not, but I just stumbled onto it. Typically when I'm debugging an ASP.NET application I test one page at a time, by right-clicking on the aspx and selecting &lt;strong&gt;View in Browser&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt; &lt;a href="http://blog2.matthidinger.com/ContentImages/ASP.NETDebuggingTip_A3DC/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ASP.NETDebuggingTip_A3DC/image_thumb.png" width="230" height="279" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I prefer this method because I can keep the browser open at all times during development and not have to compile the whole site to quickly test something simple like markup changes. The caveat to this however, is that the Visual Studio debugger is not attached to the cassini process, so I cannot hit any break points I have set. For scenarios when I need to debug and step through code, I press the Debug button, wait for the site to compile and spawn a new browser window, and then I manually navigate to the page I want to debug. Sure this isn't a very big deal, but it would be more convenient to use the browser window I already have open, which is usually already on the page I want to test.&lt;/p&gt;  &lt;p&gt;So I found this setting in the Web Application Properties for my site. Now when I enter debug mode, Visual Studio won't spawn a browser, it will simply wait for me to hit Refresh on the browser I already have open. It's a pretty minor change, but I find it to be very convenient.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog2.matthidinger.com/ContentImages/ASP.NETDebuggingTip_A3DC/image_3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blog2.matthidinger.com/ContentImages/ASP.NETDebuggingTip_A3DC/image_thumb_3.png" width="799" height="418" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d2d05082-95c8-45b5-b8f1-a1445083f3c5" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASPNET" rel="tag"&gt;ASPNET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASPNET+MVC" rel="tag"&gt;ASPNET MVC&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.matthidinger.com/aggbug/3.aspx" width="1" height="1" /&gt;&lt;img src="http://feeds.feedburner.com/~r/mhidinger/~4/zjh_X60W364" height="1" width="1"/&gt;</description>
            <dc:creator>Matt Hidinger</dc:creator>
            <guid isPermaLink="false">http://www.matthidinger.com/archive/2008/02/25/asp.net-debugging-tip.aspx</guid>
            <pubDate>Mon, 25 Feb 2008 11:38:00 GMT</pubDate>
            <wfw:comment>http://www.matthidinger.com/comments/3.aspx</wfw:comment>
            <comments>http://www.matthidinger.com/archive/2008/02/25/asp.net-debugging-tip.aspx#feedback</comments>
            <wfw:commentRss>http://www.matthidinger.com/comments/commentRss/3.aspx</wfw:commentRss>
            <trackback:ping>http://www.matthidinger.com/services/trackbacks/3.aspx</trackback:ping>
        <feedburner:origLink>http://www.matthidinger.com/archive/2008/02/25/asp.net-debugging-tip.aspx</feedburner:origLink></item>
    </channel>
</rss>
