<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mhinze.com&#187; AutoMapper in NerdDinner</title>
	<atom:link href="http://mhinze.com/category/tools/feed/" rel="self" type="application/rss+xml" />
	<link>http://mhinze.com</link>
	<description>Matt Hinze, learning in public</description>
	<lastBuildDate>Tue, 20 Apr 2010 22:42:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>AutoMapper in NerdDinner</title>
		<link>http://mhinze.com/automapper-in-nerddinner/</link>
		<comments>http://mhinze.com/automapper-in-nerddinner/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 11:00:00 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[automapper]]></category>

		<guid isPermaLink="false">http://mhinze.com/automapper-in-nerddinner/</guid>
		<description><![CDATA[Speaking of NerdDinner, Scott asked me to use it to create an AutoMapper example. AutoMapper, the brainchild of Jimmy Bogard, is an object-to-object mapper.&#160; What that means is up to you &#8211; but we&#8217;ll use it here to map from the domain model to a view model.&#160; The view model is an object heirarchy that [...]]]></description>
			<content:encoded><![CDATA[</p>
<p><a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner.aspx">Speaking</a> of <a href="http://nerddinner.codeplex.com/">NerdDinner</a>, <a href="http://www.hanselman.com/blog/">Scott</a> <a href="http://twitter.com/shanselman/status/2441262483">asked me</a> to use it to create an <a href="http://code.google.com/p/automapperhome/">AutoMapper</a> example. <a href="http://mhinze.com/wp-content/uploads/2009/07/logo.png"><img title="logo" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 15px 20px; border-right-width: 0px" height="90" alt="logo" src="http://mhinze.com/wp-content/uploads/2009/07/logo_thumb.png" width="244" align="right" border="0" /></a> </p>
<p>AutoMapper, the brainchild of <a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx">Jimmy Bogard</a>, is an object-to-object mapper.&#160; What that means is up to you &#8211; but we&#8217;ll use it here to map from the domain model to a view model.&#160; The view model is an object heirarchy that represents the screen.&#160; It&#8217;s as dumb as possible, just like the view.</p>
<p>We get a lot of nice things out of it and it helps us go faster.&#160; You can read more about it AutoMapper from <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/tags/AutoMapper/default.aspx">Jimmy</a> or at the website on <a href="http://www.codeplex.com/AutoMapper">Codeplex</a>.</p>
<p>For starters, NerdDinner isn&#8217;t the best scenario in which to apply AutoMapper.&#160; NerdDinner is very small so there&#8217;s not much reuse to harvest. For example, if you format dates the same way a million times you can use AutoMapper to only write that formatting code once.&#160; In a small application you may format dates two ways and only use the resulting text in two views.&#160; It doesn&#8217;t make a lot of sense to extract a class just for that &#8211; it will seem like a lot of overhead.&#160; </p>
<p>Also NerdDinner doesn&#8217;t have a rich domain model &#8211; there&#8217;s just not that much to do.&#160; So the AutoMapper feature of <a href="http://automapper.codeplex.com/Wiki/View.aspx?title=Flattening">flattening complex hierarchies</a> can&#8217;t be appreciated. </p>
<p>I posted <a href="http://mhinze.com/static-content/nerddinner-23425-automapper.zip"><strong>the result of this quick and dirty spike</strong></a> as a sample project &#8211; hopefully this will help you get started looking at it.</p>
<p>First, I copypasted a class to bootstrap AutoMapper:</p>
<pre class="code"><span style="color: blue">namespace </span>NerdDinner.Helpers.AutoMapper
{
    <span style="color: blue">public class </span><span style="color: #2b91af">AutoMapperConfiguration
    </span>{
        <span style="color: blue">public static void </span>Configure()
        {
            <span style="color: #2b91af">Mapper</span>.Initialize(x =&gt; x.AddProfile&lt;<span style="color: #2b91af">ViewModelProfile</span>&gt;());
        }
    }
}</pre>
<p>.. which will be called when the application starts:</p>
<pre class="code"><span style="color: blue">void </span>Application_Start()
{
    <span style="color: #2b91af">AutoMapperConfiguration</span>.Configure();

    RegisterRoutes(<span style="color: #2b91af">RouteTable</span>.Routes);

    <span style="color: #2b91af">ViewEngines</span>.Engines.Clear();
    <span style="color: #2b91af">ViewEngines</span>.Engines.Add(<span style="color: blue">new </span><span style="color: #2b91af">MobileCapableWebFormViewEngine</span>());
}</pre>
<p>I copypasted another class that will check the mapping configuration for errors, providing fast feedback should I make a mistake. </p>
<pre class="code">[<span style="color: #2b91af">TestClass</span>]
<span style="color: blue">public class </span><span style="color: #2b91af">AutoMapperConfigurationTester
</span>{
    [<span style="color: #2b91af">TestMethod</span>]
    <span style="color: blue">public void </span>Should_map_dtos()
    {
        <span style="color: #2b91af">AutoMapperConfiguration</span>.Configure();
        <span style="color: #2b91af">Mapper</span>.AssertConfigurationIsValid();
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>Now I&#8217;m ready to begin creating the view model and configuring AutoMapper. </p>
<p>To design a view model, start with the screen.&#160; What&#8217;s displayed will be represented in the model.&#160; Again: the view model is an object hierarchy that represents the user interface.&#160; I picked the Dinner Details screen, by the way. </p>
<p>The current model being used by the view was the Dinner entity itself.&#160; There was a lot of formatting in the view and a lot of duplication.</p>
<p>Almost every property was surrounded by code that would HtmlEncode it (it will be nice to have AutoMapper do this for us):</p>
<pre class="code"><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Html.Encode(Model.Title) <span style="background: #ffee62">%&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>And there is a lot of formatting to do:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">abbr </span><span style="color: red">class</span><span style="color: blue">=&quot;dtstart&quot; </span><span style="color: red">title</span><span style="color: blue">=&quot;</span><span style="background: #ffee62">&lt;%</span>= Model.EventDate.ToString(&quot;s&quot;) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&quot;&gt;
    </span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.EventDate.ToString(<span style="color: #a31515">&quot;MMM dd, yyyy&quot;</span>) <span style="background: #ffee62">%&gt;</span>
    <span style="color: blue">&lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>@<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
    </span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.EventDate.ToShortTimeString() <span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">abbr</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>Imagine a project with 300 screens and a team of analysts and you can imagine that specifying this formatting over and over again in requirements documents and planning would become tedious.&#160; Not to mention coding it.&#160; It&#8217;d be easier to just say: &#8220;Format this date in the standard way.&#8221; You can also imagine the security implications of forgetting to encode even one value.</p>
<p>In converting these screens to use a view model instead of the domain model I didn&#8217;t want to change existing functionality.&#160; So I took this:</p>
<pre class="code"><span style="background: #ffee62">&lt;%</span><span style="color: blue">@ </span><span style="color: #a31515">Page </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;System.Web.Mvc.ViewPage&lt;NerdDinner.Models.Dinner&gt;&quot;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>and changed it to this:</p>
<pre class="code"><span style="background: #ffee62">&lt;%</span><span style="color: blue">@ </span><span style="color: #a31515">Page </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;System.Web.Mvc.ViewPage&lt;DinnerDetailsViewModel&gt;&quot;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>See what I did there?&#160; I just changed the type of the Model property to a new DinnerDetailsViewModel type.</p>
<p>The view will receive a view model mapped from the domain model when I apply a special action filter to the controller action:</p>
<pre class="code">[<span style="color: #2b91af">AutoMap</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">Dinner</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DinnerDetailsViewModel</span>))]</pre>
<p>The code&#8217;s in the sample, straight from <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx">Jimmy&#8217;s post</a>.</p>
<p>I started out with DinnerDetailsViewModel being an empty class definition and used Resharper to generate each property as I encountered it.&#160; I removed the formatting and the ubiquitous encoding from the parameters, turning this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;dinnerDiv&quot; </span><span style="color: red">class</span><span style="color: blue">=&quot;vevent&quot;&gt;

    &lt;</span><span style="color: #a31515">h2 </span><span style="color: red">class</span><span style="color: blue">=&quot;summary&quot;&gt;</span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Html.Encode(Model.Title) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;

    &lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">a </span><span style="color: red">href</span><span style="color: blue">=&quot;http://feeds.technorati.com/events/</span><span style="background: #ffee62">&lt;%</span>= Url.AbsoluteAction(&quot;Details&quot;, new { id = Model.DinnerID }) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&quot;&gt;
            </span>Add event to your calendar (iCal)
        <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;

    &lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>When:<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">abbr </span><span style="color: red">class</span><span style="color: blue">=&quot;dtstart&quot; </span><span style="color: red">title</span><span style="color: blue">=&quot;</span><span style="background: #ffee62">&lt;%</span>= Model.EventDate.ToString(&quot;s&quot;) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&quot;&gt;
</span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.EventDate.ToString(<span style="color: #a31515">&quot;MMM dd, yyyy&quot;</span>) <span style="background: #ffee62">%&gt;</span>
<span style="color: blue">&lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>@<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
</span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.EventDate.ToShortTimeString() <span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">abbr</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>into this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">h2 </span><span style="color: red">class</span><span style="color: blue">=&quot;summary&quot;&gt;</span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.Title <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;

&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">a </span><span style="color: red">href</span><span style="color: blue">=&quot;http://feeds.technorati.com/events/</span><span style="background: #ffee62">&lt;%</span>= Url.AbsoluteAction(&quot;Details&quot;, new { id = Model.DinnerID }) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&quot;&gt;
        </span>Add event to your calendar (iCal)
    <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;

&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>When:<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
    </span><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Model.EventDate <span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a>I had to write a formatter to replace the custom formatting performed by the view. </p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">AttendeeNameFormatter </span>: <span style="color: #2b91af">BaseFormatter</span>&lt;<span style="color: blue">string</span>&gt;
{
    <span style="color: blue">protected override string </span>FormatValueCore(<span style="color: blue">string </span>value)
    {
        <span style="color: blue">return </span>value.Replace(<span style="color: #a31515">&quot;@&quot;</span>, <span style="color: #a31515">&quot; at &quot;</span>);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a>See how testable that is; small and reusable?</p>
<p><a href="http://11011.net/software/vspaste"></a>I also moved some methods that were previously being called from the view directly into the domain model which AutoMapper will evaluate at runtime. </p>
<p>Before:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">p </span><span style="color: red">id</span><span style="color: blue">=&quot;whoscoming&quot;&gt;
    &lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>Who's Coming:<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
    </span><span style="background: #ffee62">&lt;%</span><span style="color: blue">if </span>(Model.RSVPs.Count == 0){<span style="background: #ffee62">%&gt;
</span>          No one has registered.
    <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>After:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">p </span><span style="color: red">id</span><span style="color: blue">=&quot;whoscoming&quot;&gt;
    &lt;</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;</span>Who's Coming:<span style="color: blue">&lt;/</span><span style="color: #a31515">strong</span><span style="color: blue">&gt;
    </span><span style="background: #ffee62">&lt;%</span><span style="color: blue">if </span>(Model.IsNobodyRegistered){<span style="background: #ffee62">%&gt;
</span>          No one has registered.
    <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></pre>
<p>The view model for this screen ends up looking like this:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DinnerDetailsViewModel
</span>{
    <span style="color: blue">public string </span>Address { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>Title { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>DinnerID { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>EventDate { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>Country { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>Latitude { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>Longitude { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>Description { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>HostedBy { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public string </span>ContactPhone { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public bool </span>IsAnyoneRegistered { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public bool </span>IsNobodyRegistered { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public bool </span>IsCurrentUserRegistered { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public bool </span>IsCurrentUserHosting { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }

    <span style="color: blue">public </span><span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">RsvpViewModel</span>&gt; RSVPs { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }

    <span style="color: blue">public class </span><span style="color: #2b91af">RsvpViewModel
    </span>{
        <span style="color: blue">public string </span>AttendeeName { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    }
}</pre>
<p>The really key part is the AutoMapper configuration profile.&#160; You can group configurations with profiles.&#160; Maybe in one profile you format dates in one way, in another profile you format dates in another way.&#160; I&#8217;m just using one profile here.</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">ViewModelProfile </span>: <span style="color: #2b91af">Profile
</span>{
    <span style="color: blue">protected override string </span>ProfileName
    {
        <span style="color: blue">get </span>{ <span style="color: blue">return </span><span style="color: #a31515">&quot;ViewModel&quot;</span>; }
    }

    <span style="color: blue">protected override void </span>Configure()
    {
        AddFormatter&lt;<span style="color: #2b91af">HtmlEncoderFormatter</span>&gt;();
        ForSourceType&lt;<span style="color: #2b91af">DateTime</span>&gt;().AddFormatter&lt;<span style="color: #2b91af">StandardDateFormatter</span>&gt;();

        CreateMap&lt;<span style="color: #2b91af">Dinner</span>, <span style="color: #2b91af">DinnerDetailsViewModel</span>&gt;()
            .ForMember(x =&gt; x.IsCurrentUserRegistered, o =&gt; o.ResolveUsing&lt;<span style="color: #2b91af">CurrentUserRegisteredResolver</span>&gt;())
            .ForMember(x =&gt; x.IsCurrentUserHosting, o =&gt; o.ResolveUsing&lt;<span style="color: #2b91af">CurrentUserHostingResolver</span>&gt;())
            .ForMember(x =&gt; x.EventDate, o =&gt; o.SkipFormatter&lt;<span style="color: #2b91af">HtmlEncoderFormatter</span>&gt;());

        CreateMap&lt;<span style="color: #2b91af">RSVP</span>, <span style="color: #2b91af">DinnerDetailsViewModel</span>.<span style="color: #2b91af">RsvpViewModel</span>&gt;()
            .ForMember(x =&gt; x.AttendeeName, o =&gt; o.AddFormatter&lt;<span style="color: #2b91af">AttendeeNameFormatter</span>&gt;());
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a>Most properties of the view model are mapped conventionally.&#160; The property names match up so AutoMapper knows exactly what do do with them.&#160; AutoMapper will do a lot more for you if you&#8217;d like it to.&#160; This is actually a pretty hefty configuration.&#160; In a different scenario it&#8217;d be likely that almost everything is mapped conventionally.</p>
<p>Note the first AddFormatter call.&#160; That&#8217;s instructing AutoMapper to html encode everything.&#160; I skip it for a property later.&#160; The possibilities here are endless.&#160; One cool thing we do <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/04/24/how-we-do-mvc.aspx">in another project</a> is wrap each property in a span that&#8217;s given a conventionally named CSS class.&#160; In automated UI tests, we can use that class to find the proper element and ensure that the screen is displaying the right thing.</p>
<p><a href="http://mhinze.com/wp-content/uploads/2009/07/image.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="204" alt="image" src="http://mhinze.com/wp-content/uploads/2009/07/image_thumb.png" width="244" border="0" /></a></p>
<p>Let me know if you have any questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/automapper-in-nerddinner/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Obligatory Utility Roundup Post</title>
		<link>http://mhinze.com/obligatory-utility-roundup-post/</link>
		<comments>http://mhinze.com/obligatory-utility-roundup-post/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 05:08:27 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://mhinze.com/obligatory-utility-roundup-post/</guid>
		<description><![CDATA[I have set up a few new PCs lately in the course of getting set up on my new job.&#160; Here is what I install: Windows XP SP3 &#8211; Vista too much friction Use BlackViper&#8216;s Safe config Turn off System Restore Pop a shortcut to Start Menu in my SendTo folder for easy/lazy Launchy indexing) [...]]]></description>
			<content:encoded><![CDATA[<p>I have set up a few new PCs lately in the course of getting set up on <a href="http://mhinze.com/joined-headspring/">my new job</a>.&#160; Here is what I install:</p>
<ul>
<li>Windows XP SP3 &#8211; Vista too much friction</li>
<ul>
<li>Use <a href="http://www.blackviper.com/WinXP/servicecfg.htm">BlackViper</a>&#8216;s Safe config</li>
<li><a href="http://support.microsoft.com/kb/310405">Turn off System Restore</a></li>
<li>Pop a shortcut to Start Menu in my SendTo folder for easy/lazy Launchy indexing)</li>
<li>Set up my folder views and apply to all folders:</li>
</ul>
</ul>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="317" alt="image" src="http://mhinze.com/wp-content/uploads/2008/09/image.png" width="582" border="0" />&#160;</p>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="468" alt="image" src="http://mhinze.com/wp-content/uploads/2008/09/image1.png" width="386" border="0" /></p>
<ul>
<li>Windows XP continued</li>
<ul>
<li>Set up Windows Classic Theme and turn off any fancy UI stuff like animations</li>
</ul>
</ul>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="448" alt="image" src="http://mhinze.com/wp-content/uploads/2008/09/image2.png" width="404" border="0" /> </p>
<ul>
<li>Windows XP continued</li>
<ul>
<li> Setup toolbar to locked with just the Show Desktop shortcut</li>
</ul>
</ul>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="44" alt="image" src="http://mhinze.com/wp-content/uploads/2008/09/image3.png" width="145" border="0" />&#160;</p>
<ul>
<li><a href="http://launchy.net">Launchy</a> &#8211; gotta have it</li>
<li><a href="http://download.microsoft.com/download/7/b/6/7b6abd84-7841-4978-96f5-bd58df02efa2/winxpvirtualcdcontrolpanel_21.exe">Virtual CD ROM Control Panel</a> &#8211; mount ISOs</li>
<li>SQL Server 2005 Developer</li>
<li>Visual Studio 2008 Pro</li>
<li>.NET 3.5 SP1</li>
<li>Windows Update including IE 7 and whatever Media Player they have</li>
<li><a href="http://tortoisesvn.net/downloads">Tortoise SVN</a> (reboot here)</li>
<li>ASP.NET MVC</li>
<li><a href="http://getfirefox.com/">Firefox 3</a></li>
<ul>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/1865">Adblock Plus</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/6076">Better Gmail 2</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/3615">Delicious Bookmarks</a></li>
<li><a href="http://www.foxmarks.com/">Foxmarks</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/4287">Split Browser</a></li>
<li><a href="http://tmp.garyr.net/dev-builds/">Tab Mix Plus dev build</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a></li>
</ul>
<li><a href="http://www.red-gate.com/products/reflector/">Reflector</a></li>
<li><a href="http://sourceforge.net/project/showfiles.php?group_id=71179&amp;package_id=83198">CCTray</a></li>
<li><a href="http://www.microsoft.com/typography/ClearTypePowerToy.mspx">ClearType</a></li>
<li><a href="http://www.proggyfonts.com/index.php?menu=download">Proggy Clean</a> &#8211; font</li>
<li><a href="http://www.foxitsoftware.com/downloads/">Foxit</a></li>
<li><a href="http://www.google.com/talk/">Google Talk</a> &#8211; the only IM client that delivers searchable logs in my Gmail &#8211; required.</li>
<li><a href="http://notepad-plus.sourceforge.net/uk/download.php">Notepad++</a></li>
<li><a href="http://www.visualsvn.com/visualsvn/download/">VisualSVN</a></li>
<li><a href="http://www.testdriven.net/download.aspx">Testdriven.NET</a> &#8211; map run tests to Ctrl-T</li>
<li><a href="http://labs.adobe.com/downloads/air.html">AIR</a> / <a href="http://www.twhirl.org/project/twhirl">Twhirl</a> &#8211; to waste time</li>
<li><a href="http://www.getpaint.net/download.html">Paint.NET</a></li>
<li><a href="http://www.getpaint.net/download.html">Resharper</a></li>
<li><a href="http://get.live.com/writer/overview">Windows Live Writer</a></li>
<li><a href="http://gallery.live.com/liveItemDetail.aspx?li=d8835a5e-28da-4242-82eb-e1a006b083b9&amp;l=8">Paste from Visual Studio</a> (WLW plugin)</li>
<li><a href="http://www.7-zip.org/download.html">7-Zip</a></li>
<li><a href="http://www.codeplex.com/Terminals">Terminals</a></li>
<li><a href="http://sourceforge.net/projects/console/">Console2</a></li>
<li><a href="http://filezilla-project.org/download.php">FileZilla</a></li>
<li><a href="http://pages.interlog.com/~tcharron/wgetwin.html">wget</a></li>
<li><a href="http://www.fiddlertool.com/fiddler/">Fiddler</a></li>
<li><a href="http://gnuwin32.sourceforge.net/packages/grep.htm">grep</a></li>
<li><a href="http://www.utorrent.com/download.php">&#181;Torrent</a></li>
<li><a href="http://www.xvid.org/Downloads.15.0.html">xvid codec</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/obligatory-utility-roundup-post/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Self-signed SSL Certs on IIS 6 part 2</title>
		<link>http://mhinze.com/self-signed-ssl-cert-iis-6-part-2/</link>
		<comments>http://mhinze.com/self-signed-ssl-cert-iis-6-part-2/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 03:52:38 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[certificate]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[self]]></category>
		<category><![CDATA[ssl]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=82</guid>
		<description><![CDATA[Q: How do I install self-signed SSL certificates on two IIS 6 websites on the same server where both sites use port 443 and are configured with host headers? A: Multiple SSL sites on a single IIS server using host headers.&#160; &#60;- the answer.&#160; Basically, use SelfSSL or SSLDiag to create a cert with CN=*.example.com, [...]]]></description>
			<content:encoded><![CDATA[<p>Q: How do I install self-signed SSL certificates on <strong>two</strong> IIS 6 websites on the same server where both sites use port 443 and are configured with host headers?</p>
<p>A: <a href="http://lanestechblog.blogspot.com/2008/03/creating-self-signed-wildcard-ssl.html">Multiple SSL sites on a single IIS server using host headers</a>.&#160; &lt;- the answer.&#160; </p>
<p>Basically, use SelfSSL or SSLDiag to create a cert with CN=*.example.com, then just point the second site to that cert in the Directory Security tab.&#160; Also, configure secure server bindings using adsutil (found in c:\inetpub\adminscripts).</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/self-signed-ssl-cert-iis-6-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Self-signed SSL certs on IIS 6</title>
		<link>http://mhinze.com/self-signed-ssl-certs-on-iis-6/</link>
		<comments>http://mhinze.com/self-signed-ssl-certs-on-iis-6/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 21:00:25 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[443]]></category>
		<category><![CDATA[certificate]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[iis 6]]></category>
		<category><![CDATA[selfssl]]></category>
		<category><![CDATA[ssl]]></category>

		<guid isPermaLink="false">http://mhinze.com/self-signed-ssl-certs-on-iis-6/</guid>
		<description><![CDATA[Q: How do I install a self-signed SSL certificate on an IIS 6 website? A: Use the SelfSSL utility that comes with the IIS Resource kit! http://codeforeternity.com/blogs/technology/archive/2008/02/15/creating-self-signed-ssl-certificates-on-iis-6-0-and-windows-server-2003.aspx &#160; Q: How do I install self-signed SSL certificates on two IIS 6 websites on the same server? A: SelfSSL.exe is bugged.&#160; Install SSLDiag and use its embedded [...]]]></description>
			<content:encoded><![CDATA[<p>Q: How do I install a self-signed SSL certificate on an IIS 6 website?</p>
<p>A: Use the SelfSSL utility that comes with the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=56FC92EE-A71A-4C73-B628-ADE629C89499&amp;displaylang=en">IIS Resource kit</a>!</p>
<p><a title="http://codeforeternity.com/blogs/technology/archive/2008/02/15/creating-self-signed-ssl-certificates-on-iis-6-0-and-windows-server-2003.aspx" href="http://codeforeternity.com/blogs/technology/archive/2008/02/15/creating-self-signed-ssl-certificates-on-iis-6-0-and-windows-server-2003.aspx">http://codeforeternity.com/blogs/technology/archive/2008/02/15/creating-self-signed-ssl-certificates-on-iis-6-0-and-windows-server-2003.aspx</a></p>
<p>&nbsp;</p>
<p>Q: How do I install self-signed SSL certificates on <strong>two</strong> IIS 6 websites on the same server?</p>
<p>A: SelfSSL.exe is bugged.&nbsp; Install <a href="http://www.microsoft.com/downloads/details.aspx?familyid=cabea1d0-5a10-41bc-83d4-06c814265282&amp;displaylang=en">SSLDiag</a> and use its embedded SelfSSL tool.</p>
<p>The problem with two certs, two sites on the same server is strange.&nbsp; You install a cert on website A and it works great.&nbsp; You install another cert on B and B works great while A breaks.&nbsp; And etc.</p>
<p><a title="http://ewright.spaces.live.com/blog/cns!C0C3DF24CE16DC2F!169.entry" href="http://ewright.spaces.live.com/blog/cns!C0C3DF24CE16DC2F!169.entry">http://ewright.spaces.live.com/blog/cns!C0C3DF24CE16DC2F!169.entry</a></p>
<p>ssldiag /selfssl /V:365 /N:CN=www.point2.com /S:1834870997</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/self-signed-ssl-certs-on-iis-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linq to NHibernate in 10 minutes</title>
		<link>http://mhinze.com/linq-to-nhibernate-in-10-minutes/</link>
		<comments>http://mhinze.com/linq-to-nhibernate-in-10-minutes/#comments</comments>
		<pubDate>Tue, 22 Jul 2008 12:45:59 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[codecampserver]]></category>
		<category><![CDATA[linq]]></category>
		<category><![CDATA[nhibernate]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=52</guid>
		<description><![CDATA[If you are curious about Linq to NHibernate and want to quickly check it out, here is an easy way to do it. Check out a copy of the CodeCampServer source (svn).&#160; CodeCampServer is easy to work with because it has good tests on an already-working NHibernate implementation. Check out a copy of NH Contrib [...]]]></description>
			<content:encoded><![CDATA[<p>If you are curious about <a href="http://www.ayende.com/Blog/archive/2007/03/17/Implementing-Linq-for-NHibernate-A-How-To-Guide--Part.aspx">Linq to NHibernate</a> and want to quickly check it out, here is an easy way to do it.</p>
<p>Check out a copy of the <a href="http://codecampserver.org">CodeCampServer</a> source (<a href="http://codecampserver.googlecode.com/svn/trunk/">svn</a>).&nbsp; CodeCampServer is easy to work with because it has good tests on an already-working NHibernate implementation.</p>
<p>Check out a copy of <a href="http://sourceforge.net/projects/nhcontrib/">NH Contrib</a> (<a href="https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/">svn</a>), open the NHibernate.Linq solution in Visual Studio and build. You may have to remove the compiler flag that indicates .NET 3.5 sp1 is available.</p>
<p>Open the CodeCampServer.sln and remove the NHibernate.dll reference from the DataAccess and IntegrationTests projects.&nbsp; Add a reference to NHibernate.dll from the NHibernate.Linq bin directory.&nbsp; Build and run tests.&nbsp; I had to play with the <a href="http://codecampserver.googlecode.com/svn/trunk/src/IntegrationTests/DataAccess/DatabaseTesterBase.cs">DatabaseTesterBase.recreateDatabase()</a> method because I think are are still some bugs in Export():</p>
<pre class="code"><span style="color: blue">public static void </span>recreateDatabase()
{
    <span style="color: blue">var </span>exporter = <span style="color: blue">new </span><span style="color: #2b91af">SchemaExport</span>(<span style="color: blue">new </span><span style="color: #2b91af">HybridSessionBuilder</span>().GetConfiguration());
    exporter.Drop(<span style="color: blue">false</span>, <span style="color: blue">true</span>);
    exporter.Create(<span style="color: blue">false</span>, <span style="color: blue">true</span>);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Now add a reference to NHibernate.Linq.dll in the DataAccess project. You can start <a href="http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx">writing queries</a> and check your work with the integration tests that already exist. Here are a few simple queries for <a href="http://codecampserver.googlecode.com/svn/trunk/src/DataAccess/Impl/ConferenceRepository.cs">ConferenceRepository</a>:</p>
<p><a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">public </span><span style="color: #2b91af">Conference</span>[] GetAllConferences()
{
    <span style="color: #2b91af">ISession </span>session = getSession();
    <span style="color: blue">var </span>query = <span style="color: blue">from </span>conference <span style="color: blue">in </span>session.Linq&lt;<span style="color: #2b91af">Conference</span>&gt;() <span style="color: blue">select </span>conference;
    <span style="color: blue">return </span>query.ToList().ToArray();
}

<span style="color: blue">public </span><span style="color: #2b91af">Conference </span>GetConferenceByKey(<span style="color: blue">string </span>key)
{
    <span style="color: #2b91af">ISession </span>session = getSession();
    <span style="color: blue">var </span>query = <span style="color: blue">from </span>conference <span style="color: blue">in </span>session.Linq&lt;<span style="color: #2b91af">Conference</span>&gt;()
                <span style="color: blue">where </span>conference.Key == key
                <span style="color: blue">select </span>conference;
    <span style="color: blue">return </span>query.Distinct().Single();
}

<span style="color: blue">public </span><span style="color: #2b91af">Conference </span>GetFirstConferenceAfterDate(<span style="color: #2b91af">DateTime </span>date)
{
    <span style="color: #2b91af">ISession </span>session = getSession();
    <span style="color: blue">var </span>query = <span style="color: blue">from </span>conference <span style="color: blue">in </span>session.Linq&lt;<span style="color: #2b91af">Conference</span>&gt;()
                <span style="color: blue">where </span>conference.StartDate &gt;= date
                <span style="color: blue">orderby </span>conference.StartDate
                <span style="color: blue">select </span>conference;
    <span style="color: blue">return </span>query.First();
}

<span style="color: blue">public </span><span style="color: #2b91af">Conference </span>GetMostRecentConference(<span style="color: #2b91af">DateTime </span>date)
{
    <span style="color: #2b91af">ISession </span>session = getSession();
    <span style="color: blue">var </span>query = <span style="color: blue">from </span>conference <span style="color: blue">in </span>session.Linq&lt;<span style="color: #2b91af">Conference</span>&gt;()
            <span style="color: blue">where </span>conference.EndDate &lt;= date
            <span style="color: blue">select </span>conference;
    query.OrderByDescending(conference =&gt; conference.EndDate);
    <span style="color: blue">return </span>query.First();
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/linq-to-nhibernate-in-10-minutes/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Long delays deleting a file in Visual Studio</title>
		<link>http://mhinze.com/slow-file-delete-visual-studio/</link>
		<comments>http://mhinze.com/slow-file-delete-visual-studio/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 17:08:33 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=46</guid>
		<description><![CDATA[For months I have been suffering from long delays when I delete a file from solution explorer in Visual Studio.&#160; Minutes&#8230; slow, dreadful minutes.&#160;&#160; I thought it was Resharper’s fault or VisualSVN&#8217;s but nay.&#160; It’s because I have a large recycle bin, which is fully scanned every time you delete a file.&#160; After I emptied [...]]]></description>
			<content:encoded><![CDATA[<p>For <em>months</em> I have been suffering from long delays when I delete a file from solution explorer in Visual Studio.&nbsp;
<p>Minutes&#8230; slow, dreadful minutes.&nbsp;&nbsp;
<p>I thought it was Resharper’s fault or VisualSVN&#8217;s but nay.&nbsp; It’s because I have a large recycle bin, which is fully scanned every time you delete a file.&nbsp; After I emptied the recycle bin files deleted much faster.
<p>Via <a href="http://tech.groups.yahoo.com/group/altdotnet/message/11685">Jeff Brown on the alt.net list</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/slow-file-delete-visual-studio/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Refactoring DRY tests with Resharper&#8217;s Inline Method</title>
		<link>http://mhinze.com/refactoring-dry-tests-with-inline-method/</link>
		<comments>http://mhinze.com/refactoring-dry-tests-with-inline-method/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 15:00:53 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[dry]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[resharper]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=45</guid>
		<description><![CDATA[Dan North, in a recent article about DRY tests, says: [Tests] are the documentation narrative that will guide future programmers (including yourself when you come back to change this code in three months time and you’ve forgotten what it does). In this case, clarity of intent is found in the quality of the narrative, not [...]]]></description>
			<content:encoded><![CDATA[<p>Dan North, in a <a href="http://dannorth.net/2008/06/let-your-examples-flow">recent article about DRY tests</a>, says:</p>
<blockquote><p>[Tests] are the documentation narrative that will guide future programmers (including yourself when you come back to change this code in three months time and you’ve forgotten what it does). In this case, clarity of intent is found in the quality of the narrative, not necessarily in minimising duplication.</p>
</blockquote>
<p>I had a painful experience with DRY tests the other day.&nbsp; The code looked something like this, but on a larger, more hideous scale:</p>
<pre class="code">[<span style="color: #2b91af">Fact</span>]
<span style="color: blue">public void </span>SomeServiceWorks()
{
    <span style="color: blue">using </span>(<span style="color: blue">var </span>service = <span style="color: blue">new </span><span style="color: #2b91af">Service</span>())
    {
        RunTest(service);
    }
}

[<span style="color: #2b91af">Fact</span>]
<span style="color: blue">public void </span>AnotherTest()
{
    <span style="color: blue">using </span>(<span style="color: blue">var </span>service = <span style="color: #2b91af">Service</span>.MyService)
    {
        CheckProps(service);
    }
}

<span style="color: blue">private static void </span>CheckProps(<span style="color: #2b91af">Service </span>service)
{
    <span style="color: #2b91af">Assert</span>.NotNull(service.OtherThing);
    RunTest(service);
}

<span style="color: blue">private static void </span>RunTest(<span style="color: #2b91af">Service </span>service)
{
    <span style="color: #2b91af">Assert</span>.NotNull(service.Something);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>So while the code is not clear, it is easy to see what the author was trying to do &#8211; keep his tests DRY.&nbsp; With a lot of tests this makes it very difficult to understand exactly what is going on.</p>
<p>Resharper has a nifty <a href="http://www.jetbrains.com/resharper/features/newfeatures.html#New_Refactorings">new refactoring</a> that lets us do an <a href="http://www.refactoring.com/catalog/inlineMethod.html">Inline Method</a> to clarify these tests.&nbsp; Just insert at the method name and use the Ctrl-Alt-N shortcut:</p>
<p>&nbsp;</p>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="424" alt="image" src="http://mhinze.com/wp-content/uploads/2008/07/image-thumb3.png" width="659" border="0"></p>
<p>I think the resulting code is much easier to read.</p>
<pre class="code">[<span style="color: #2b91af">Fact</span>]
<span style="color: blue">public void </span>SomeServiceWorks()
{
    <span style="color: blue">using </span>(<span style="color: blue">var </span>service = <span style="color: blue">new </span><span style="color: #2b91af">Service</span>())
    {
        <span style="color: #2b91af">Assert</span>.NotNull(service.Something);
    }
}

[<span style="color: #2b91af">Fact</span>]
<span style="color: blue">public void </span>AnotherTest()
{
    <span style="color: blue">using </span>(<span style="color: blue">var </span>service = <span style="color: #2b91af">Service</span>.MyService)
    {
        <span style="color: #2b91af">Assert</span>.NotNull(service.OtherThing);
        <span style="color: #2b91af">Assert</span>.NotNull(service.Something);
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/refactoring-dry-tests-with-inline-method/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Audit options with NHibernate</title>
		<link>http://mhinze.com/audit-options-with-nhibernate/</link>
		<comments>http://mhinze.com/audit-options-with-nhibernate/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 13:55:27 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[auditing]]></category>
		<category><![CDATA[ddd]]></category>
		<category><![CDATA[nhibernate]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=43</guid>
		<description><![CDATA[In this post I am talking about auditing for the business, not the technical infrastructure.&#160; As an example story, users will want to see certain fields highlighted on a grid if that field has changed in the last week, and the info about the change (who, when, what) should be a tooltip for the cell. [...]]]></description>
			<content:encoded><![CDATA[<p>In this post I am talking about auditing for the business, not the technical infrastructure.&nbsp; As an example story, users will want to see certain fields highlighted on a grid if that field has changed in the last week, and the info about the change (who, when, what) should be a tooltip for the cell.</p>
<p><strong>Database trigger</strong></p>
<ul>
<li>See Jon Galloway&#8217;s post on <a href="http://weblogs.asp.net/jgalloway/archive/2008/01/27/adding-simple-trigger-based-auditing-to-your-sql-server-database.aspx">Auditing with SQL Server</a></li>
<li>To <a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:59412348055">generate an audit trigger in oracle</a> you can do something similar.</li>
</ul>
<p><strong>NH Interceptor</strong> (per NH in action and the <a href="http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html_single/#manipulatingdata-interceptors">NH docs</a>)</p>
<p><strong>NH Listener</strong> (per the <a href="http://www.hibernate.org/318.html">Hibernate docs</a>)</p>
<p><strong>Domain model</strong></p>
<p>Because auditing is a simple application of interceptors there is a lot of guidance online about that approach, and using an interceptor was my first attempt at auditing. </p>
<p>But since the concept of an audit entry is important to the application (and the users!), it makes sense to promote this concept to a domain object.&nbsp; Reporting is simple and the behavior is easier to manage.&nbsp; Create a class called AuditEntry (with supporting mapping file) and hang collections of AuditEntry from the entity. Manage this collection in regular behavior:</p>
<pre class="code"><span style="color: blue">public virtual void </span>ChangeStatus(<span style="color: #2b91af">Employee </span>employee, <span style="color: #2b91af">DateTime </span>time, <span style="color: #2b91af">OrderStatus </span>status)
{
    <span style="color: blue">if</span>(<span style="color: blue">this</span>.Status != status)
    {
        <span style="color: #2b91af">AuditEntry </span>entry = <span style="color: blue">new </span><span style="color: #2b91af">AuditEntry</span>(employee, time, <span style="color: blue">this</span>.Status, status);
        _auditEntries.Add(entry);
    }
    Status = status;
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>After having gone down the database trigger path and the interceptor path and encountering friction I now recommend the domain model approach.</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/audit-options-with-nhibernate/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tree Surgeon 2.0 released</title>
		<link>http://mhinze.com/treesurgeon-20-released/</link>
		<comments>http://mhinze.com/treesurgeon-20-released/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 10:51:47 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[treesurgeon]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=39</guid>
		<description><![CDATA[Bil Simser just released Tree Surgeon 2.0. TreeSurgeon automates the creation of a new project development tree, complete with a VS solution, a test project, a console project and a &#8220;core&#8221; project.&#160; It also automates the creation of a Nant build file which is set up to generate an Ncover report. &#160;&#160; The first thing [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://weblogs.asp.net/bsimser/archive/2008/06/30/tree-surgeon-2-0-released.aspx">Bil Simser just released</a> <a href="http://www.codeplex.com/treesurgeon">Tree Surgeon 2.0</a>.</p>
<p>TreeSurgeon automates the creation of a new project development tree, complete with a VS solution, a test project, a console project and a &#8220;core&#8221; project.&nbsp; It also automates the creation of a Nant build file which is set up to generate an Ncover report.</p>
<p><a href="http://mhinze.com/wp-content/uploads/2008/07/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="266" alt="image" src="http://mhinze.com/wp-content/uploads/2008/07/image-thumb.png" width="191" border="0"></a>&nbsp;&nbsp; </p>
<p>The first thing I wanted to do was add other tools I use in almost every project.&nbsp; This turned out to be way easy.&nbsp; Just copy the binaries in the skeleton folder (these get copied to every new tree) and edit the project file templates to add a reference.</p>
<p>Here I added Rhino Mocks:</p>
<p><a href="http://mhinze.com/wp-content/uploads/2008/07/image1.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="269" alt="image" src="http://mhinze.com/wp-content/uploads/2008/07/image-thumb1.png" width="539" border="0"></a>&nbsp;</p>
<p>And added a few lines to the template file:</p>
<p><a href="http://mhinze.com/wp-content/uploads/2008/07/image2.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="403" alt="image" src="http://mhinze.com/wp-content/uploads/2008/07/image-thumb2.png" width="630" border="0"></a> </p>
<p>Easy!&nbsp; Thanks Bil!</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/treesurgeon-20-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Resolving HttpContext members using Ninject providers</title>
		<link>http://mhinze.com/httpcontext-ninject-providers/</link>
		<comments>http://mhinze.com/httpcontext-ninject-providers/#comments</comments>
		<pubDate>Tue, 24 Jun 2008 15:17:42 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[ninject]]></category>

		<guid isPermaLink="false">http://mhinze.com/?p=28</guid>
		<description><![CDATA[I am building a simple &#8220;single sign-on&#8221; ASP.NET application that interprets the current user&#8217;s ASP.NET integrated security credentials to a vendor site&#8217;s credentials.&#160; One of the services I wrote required the IIdentity as a constructor parameter to begin the interpretation process.&#160; This was straightforward with regards to TDD &#8211; I simply mocked the IIdentity and [...]]]></description>
			<content:encoded><![CDATA[<p>I am building a simple &#8220;single sign-on&#8221; ASP.NET application that interprets the current user&#8217;s ASP.NET integrated security credentials to a vendor site&#8217;s credentials.&nbsp; One of the services I wrote required the <a href="http://msdn.microsoft.com/en-us/library/system.security.principal.iidentity.aspx">IIdentity</a> as a constructor parameter to begin the interpretation process.&nbsp; </p>
<p>This was straightforward with regards to TDD &#8211; I simply mocked the IIdentity and kept going.&nbsp; When I began implementing dependency injection with an IoC container I struggled until I found a nice way to do this with <a href="http://ninject.org/">Ninject</a>.</p>
<p>Ninject offers a pretty cool <a href="http://davidhayden.com/blog/dave/archive/2008/06/20/NinjectDependencyInjectionASPNETWebPagesSample.aspx">suite of ASP.NET integration points</a> in the <a href="http://ninject.googlecode.com/svn/trunk/src/Framework/Web/">Ninject.Framework.Web</a> namespace.&nbsp; And without using System.Web.Abstractions, the best way I found to resolve a property of HttpContext.Current (User.Identity in my case) was to leverage a provider.</p>
<p class="post-update">Update (6/25): Duncan Godwin, in the comments, explained what&#8217;s perhaps a better way to do this using ToFactoryMethod()</p>
<h3>Ninject providers</h3>
<p><a href="http://dojo.ninject.org/wiki/display/NINJECT/Providers+and+the+Activation+Context">Ninject providers</a>, IProvider and the simple implementation SimpleProvider&lt;T&gt;, allow the developer to customize the resolution of these hard-to inject objects.&nbsp; We&#8217;re <a href="http://groups.google.com/group/ninject/browse_thread/thread/6ca3bc6dd2078cc5">talking providers today</a> on the <a href="http://groups.google.com/group/ninject">Ninject list</a>.</p>
<p>Here&#8217;s the one I used to resolve IIdentity:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">WebIdentityProvider </span>: <span style="color: #2b91af">SimpleProvider</span>&lt;<span style="color: #2b91af">IIdentity</span>&gt;
{
    <span style="color: blue">protected override </span><span style="color: #2b91af">IIdentity </span>CreateInstance(<span style="color: #2b91af">IContext </span>context)
    {
        <span style="color: blue">return </span><span style="color: #2b91af">HttpContext</span>.Current.User.Identity;
    }

    <span style="color: blue">public override bool </span>IsCompatibleWith(<span style="color: #2b91af">IContext </span>context)
    {
        <span style="color: blue">return </span><span style="color: #2b91af">HttpContext</span>.Current != <span style="color: blue">null</span>;
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Here is sample code like I used in Global.asax.cs:</p>
<p><a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">Global </span>: <span style="color: #2b91af">NinjectHttpApplication
</span>{
    <span style="color: green">// ...

    </span><span style="color: blue">protected override </span><span style="color: #2b91af">IKernel </span>CreateKernel()
    {
        <span style="color: blue">var </span>module = <span style="color: blue">new </span><span style="color: #2b91af">InlineModule</span>(
            m =&gt; m.Bind&lt;<span style="color: #2b91af">IIdentity</span>&gt;().ToProvider&lt;<span style="color: #2b91af">WebIdentityProvider</span>&gt;(),
            m =&gt; m.Bind&lt;<span style="color: #2b91af">IIdentityService</span>&gt;().To&lt;<span style="color: #2b91af">IdentityService</span>&gt;(),
            m =&gt; m.Bind&lt;<span style="color: #2b91af">IDisplayName</span>&gt;().To&lt;<span style="color: #2b91af">DisplayName</span>&gt;()
            );
        <span style="color: blue">return new </span><span style="color: #2b91af">StandardKernel</span>(module, <span style="color: blue">new </span><span style="color: #2b91af">Log4netModule</span>());
    }
}</pre>
<p>When binding to the provider HttpContext.Current and the user&#8217;s IIdentity are available.</p>
<p>I have a feeling this isn&#8217;t the last one I&#8217;ll use.</p>
<p><a href="http://mhinze.com/static-content/NinjectWeb.zip">Here is sample code</a> with log4net&#8217;s <a href="http://logging.apache.org/log4net/release/sdk/log4net.Appender.AspNetTraceAppender.html">AspNetTraceAppender</a> turned on (using <a href="http://mhinze.com/logging-with-ninject/">Ninject logging</a> of course).</p>
]]></content:encoded>
			<wfw:commentRss>http://mhinze.com/httpcontext-ninject-providers/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
