<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Jonathan George&#039;s Blog</title>
	<atom:link href="http://jonathangeorge.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathangeorge.co.uk</link>
	<description>True confessions of a technical architect</description>
	<lastBuildDate>Fri, 13 Apr 2012 03:59:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jonathangeorge.co.uk' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/c6670528bd320dfa4e609e09f50e5df4?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Jonathan George&#039;s Blog</title>
		<link>http://jonathangeorge.co.uk</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jonathangeorge.co.uk/osd.xml" title="Jonathan George&#039;s Blog" />
	<atom:link rel='hub' href='http://jonathangeorge.co.uk/?pushpress=hub'/>
		<item>
		<title>Making SharpArch 2.0: Who Can Help Me? Part 1</title>
		<link>http://jonathangeorge.co.uk/2011/05/17/making-sharparch-2-0-who-can-help-me-part-1/</link>
		<comments>http://jonathangeorge.co.uk/2011/05/17/making-sharparch-2-0-who-can-help-me-part-1/#comments</comments>
		<pubDate>Tue, 17 May 2011 18:34:19 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[s#arp architecture]]></category>
		<category><![CDATA[who can help me]]></category>

		<guid isPermaLink="false">https://jonathangeorge.wordpress.com/2011/05/17/making-sharparch-2-0-who-can-help-me-part-1/</guid>
		<description><![CDATA[Who Can Help Me? started life towards the end of 2009, after myself, Howard, James, and a host of other amazing ex-colleagues worked together on www.fancydressoutfitters.co.uk. We’d built the client-facing site using S#arp Arch and a bunch of other open source tools, and wanted to put together a vastly simplified sample app demonstrating how we [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=54&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Who Can Help Me? started life towards the end of 2009, after myself, Howard, James, and a host of other amazing ex-colleagues worked together on <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a>. We’d built the client-facing site <a href="http://groups.google.com/group/sharp-architecture/browse_thread/thread/9df324a3dc36decb/32efa2ab67c7f87f?lnk=gst&amp;q=site+live#32efa2ab67c7f87f" target="_blank">using S#arp Arch and a bunch of other open source tools</a>, and wanted to put together a vastly simplified sample app demonstrating how we did it. And so, we build Who Can Help Me? and put it out there for the community to play with.</p>
<p>Despite not originally being intended as a S#arp Arch demo, it was adopted as one. Which gave rise to the question: what do we do with it for S#arp Arch 2.0? When we built it, we wanted to demonstrate the architecture and toolset we used for an enterprise-level e-commerce site. We didn’t go out of our way to demonstrate any specific patterns, and we made no effort to demonstrate many of the nice features offered by the different tools we used. After some back and forth between the team we decided that things have moved on in the last 2 years, and whilst we are all still proud of the e-commerce site it was based on, WCHM is not representative of the way we choose to build websites today.</p>
<p>In addition, those who follow <a href="http://ayende.com" target="_blank">Ayende’s blog</a> may have noticed his <a href="http://ayende.com/blog/4812/code-review-who-can-help-me" target="_blank">recent code review on WCHM</a>. He raised some valid issues with the code, and fortunately there are several upcoming SA 2.0 features that will help me address them. So here’s the hit list for how WCHM 1.9.6 will go not only to 2.0, but also to being a true Sharp Architecture sample app.</p>
<p>Firstly, relevant points from Ayende’s review:</p>
<h2>The mapping sucks</h2>
<p>The pattern we adopted when writing our controllers is as follows:</p>
<ul>
<li>Receive request. </li>
<li>Make request to tasks layer (aka application services); get domain entities returned. </li>
<li>Use mapper to map entities to view models. </li>
<li>Return view result, passing view model. </li>
</ul>
<p>This looks extremely simple on paper, and for the most part it is. However it has a few issues:</p>
<ul>
<li>It can get messy quickly, especially if your view requires several disparate pieces of data – in this case, the controller makes multiple calls to the tasks layer to retrieve the required data, which is then passed into a mapper. Often this mapper will use other mappers to map collections or child view models. </li>
<li>It is, as Ayende pointed out, a breeding ground for SELECT N+1 issues. </li>
</ul>
<p>S#arp Arch 2.0 has a solution to this problem in the form of the <a href="http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html" target="_blank">Enhanced Query Object</a> approach. So, to populate a view model we no longer make calls into the tasks layer. Instead we use a query object which retrieves all necessary data. Because the EQO talks directly to the NHibernate session we can bypass the layers of abstraction that Ayende derides in his posts, replacing it with LINQ/Criteria/HQL/named queries/whatever else we think is the right fit for the problem. </p>
<h2>Too many specifications</h2>
<p>There are quite a few specifications in the domain layer. They fit nicely into two categories:</p>
<ol>
<li><strong>Specifications that just shouldn’t be there at all</strong>. This covers ProfileByIdSpecification and CategoryByIdSpecification. Simply put, these shouldn’t exist. Instead, the FindOne method on the relevent repository should be used, which simply passes through to the Session.Get&lt;T&gt; method. </li>
<li><strong>Specifications that aren’t really specifications</strong>. Unfortunately, this covers the remainder of the specifications. The problem is, a specification is really intended for codifying a business rule – so an <strong>OverdueInvoiceSpecification</strong> would capture what it means for an invoice to be overdue. When you look at it in that way, it’s pretty obvious that TagByNameSpecification (for example) is not codifying any business rule and as such has no place in the domain layer. </li>
</ol>
<p>Unfortunately this means I’ll be deleting all the existing specifications. Hopefully I’ll be able to come up with a good example or two to replace them with.</p>
<p>Now, onto a few of my own points:</p>
<h2>Anaemic Domain Model</h2>
<p>Anaemic Domain Model (<a href="http://en.wikipedia.org/wiki/Anemic_Domain_Model" target="_blank">Wikipedia</a>, <a href="http://www.martinfowler.com/bliki/AnemicDomainModel.html" target="_blank">Fowler</a>) normally – and in my opinion, somewhat unfairly – gets labelled as an anti-pattern. It actually made a lot of sense in the original application, because in fact there was no domain logic to speak of. However, since Sharp Arch has all the DDD terms baked in, WCHM needs to do more than pay lip service to these, so I’ll be doing my best to improve this. </p>
<h2>No obviously identified aggregate roots</h2>
<p>Following on from the previous point – the code in WCHM doesn’t follow the DDD practice of accessing entities via aggregate roots only, so this will be another thing to improve.</p>
<h2>Replace existing Tasks with Commands</h2>
<p>WCHM currently uses a traditional tasks layer, with the different methods grouped up into a few different application services – CategoryTasks, ProfileTasks, etc. As described above, the query methods will be pulled out of these tasks and moved into queries that will be homed alongside the controllers. The remaining methods will be separated into commands, which will remain in the Tasks layer.</p>
<h2>Merge <strong>Web.Controllers</strong> and <strong>Web</strong></h2>
<p>As detailed in <a href="http://blog.sharparchitecture.net/post/Making-SharpArch-20-Introduction.aspx" target="_blank">Geoff’s Introductory post in this series</a>, we’re merging controllers back into the main web project, and renaming to Presentation.</p>
<h1>Summary</h1>
<p>In reading this, you might think that I’m saying WCHM is a steaming pile of something unpleasant. Nothing could be further from the truth – <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> is a project that I’m proud to have been part of, and WCHM is an extension of that. The site has been running with no significant unplanned downtime for nearly 2 years now, from a project that went from nothing to live in just ten 2 week sprints. </p>
<p>However, I hate it when code I’ve written is allowed to stagnate – like most of us, I look back on code I’ve written and think about all the ways it could be better. I hope that there will never be a day when I look back on one- or two-year old code and realise I’ve learned nothing since it was written. In the meantime, I’d appreciate any feedback people have on WCHM and this post.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: <a href='http://jonathangeorge.co.uk/tag/sarp-architecture/'>s#arp architecture</a>, <a href='http://jonathangeorge.co.uk/tag/who-can-help-me/'>who can help me</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/54/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=54&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2011/05/17/making-sharparch-2-0-who-can-help-me-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Making SharpArch 2.0: Repositories, Build and Packaging</title>
		<link>http://jonathangeorge.co.uk/2011/04/14/making-sharparch-2-0-repositories-build-and-packaging/</link>
		<comments>http://jonathangeorge.co.uk/2011/04/14/making-sharparch-2-0-repositories-build-and-packaging/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 22:04:30 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[packaging]]></category>

		<guid isPermaLink="false">https://jonathangeorge.wordpress.com/2011/04/14/making-sharparch-2-0-repositories-build-and-packaging/</guid>
		<description><![CDATA[Following on from Geoff’s first post in this series, this post details the move from two repositories (Sharp-Architecture and Sharp-Architecture-Contrib) to the current set up, including how we’ve restructured the repositories themselves and included a common build system across everything. TL;DR We’ve moved all the SA repositories into a single GitHub organisation, separated samples into [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=52&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Following on from <a href="http://blog.sharparchitecture.net/post/Making-SharpArch-20-Introduction.aspx" target="_blank">Geoff’s first post in this series</a>, this post details the move from two repositories (Sharp-Architecture and Sharp-Architecture-Contrib) to the current set up, including how we’ve restructured the repositories themselves and included a common build system across everything.</p>
<h2>TL;DR</h2>
<p>We’ve moved all the SA repositories into a single GitHub organisation, separated samples into their own repositories, brought the repository structures in line with one another, and implemented a common build system shared by the solution in each repository.</p>
<h2>Some Background</h2>
<p>Until the end of last year, Sharp Arch consisted of two repositories. We had Sharp-Architecture, which contained SA itself and the Northwind sample app, and Sharp-Architecture-Contrib, which was pretty much what it said on the tin. The master versions of these repositories lived in Billy’s GitHub account.</p>
<p>When we started talking about Sharp Arch 2.0, Billy had already taken a step back from the project. Who Can Help Me? had been adopted as a second sample application (with the master version living in my GitHub account), and we had big plans for both Sharp Arch itself and the sample apps we provide for it. As a result, we made a few decisions:</p>
<ul>
<li>We’d bring all of the Sharp Architecture repositories under one roof so that it was obvious what was “official” Sharp Arch and what wasn’t </li>
<li>We’d provide each sample app – including Northwind – in it’s own repository, rather than having a single massive repository containing SA core and all of it’s samples. </li>
<li>We’d adopt a common structure for all our repositories, so that people know what to expect when getting into each one. </li>
<li>We’d provide a common way of building all of the projects, so that we didn’t need something specific in each repository. </li>
</ul>
<h2>Step 1. Sharp Architecture organisation on GitHub</h2>
<p>This was the easy bit; as you probably already know if you’re a Sharp Arch user, we’ve created a new GitHub organisation that our repositories can call home. It’s at <a href="https://github.com/sharparchitecture/">https://github.com/sharparchitecture/</a> and at time of writing, contains the following repositories:</p>
<ul>
<li><strong>Sharp-Architecture</strong>       <br />The core Sharp Arch projects. This currently has a <strong>master </strong>branch, which is the source of the current release (1.9.6), and a <strong>develop </strong>branch which contains the restructured work in progress version. </li>
<li><strong>Sharp-Architecture-Features</strong>       <br />An all-new, 2.0 repository containing code for the different persistence options we’re providing for Sharp Arch 2.0. Because it’s new for 2.0, the master branch of this repository contains the code that’s aligned with the develop branch in the main Sharp-Architecture repo. Apologies if this is somewhat confusing. </li>
<li><strong>Sharp-Architecture-Contrib</strong>       <br />As with the core repo, the <strong>master </strong>branch contains the source of the current release and the <strong>develop </strong>branch contains the Contrib project that will support SA 2.0. </li>
<li><strong>Sharp-Architecture-Build</strong>       <br />Common build system for the Sharp Architecture solutions – see below for more information. </li>
<li><strong>Northwind</strong>       <br />The original SA sample app. As before, <strong>master</strong> contains the code that goes along with the current SA release, and <strong>develop </strong>will be updated to use SA 2.0. </li>
<li><strong>Who-Can-Help-Me</strong>       <br />Sharp Arch’s second sample app. As before, <strong>master</strong> contains the code that goes along with the current SA release, and <strong>develop </strong>will be updated to use SA 2.0. </li>
<li><strong>Sharp-Architecture-Template</strong>       <br />A new kid on the block, this will eventually contain the reference project structure that is used to generate the Templify package for SA. At the moment, our Templify package is built from the Northwind sample, but we are intending to change this as part of the 2.0 release. </li>
<li><strong>Sharp-Architecture-Cookbook</strong>       <br />Another newbie – this is a new sample application that differs from Northwind and Who Can Help Me? in that it doesn’t intend to be a real world example of how to use SA to build an app. Instead, it will contain a series of examples of different things that can be done with SA. “Recipies” that you might find in the cookbook could include the different ways of setting up NHibernate (Automapping, Fluent and traditional HBM mapping), using SA with WCF, usage scenarios for LinqRepository and the Specification pattern and so on. Our hope is that over time, this will become the main reference for “how do I…” questions. </li>
</ul>
<h2>Step 2. Repository structure</h2>
<p>We decided to standardise on the repository structure used in WCHM. At the top level, it contains the following folders:</p>
<ul>
<li><strong>Build        <br /></strong>Build scripts for the project – see below for more details </li>
<li><strong>BuildSystem</strong>       <br />Git submodule used to pull the common build bits and pieces from Sharp-Architecture-Build. </li>
<li><strong>Common</strong>       <br />Contains any common files used across multiple projects. In practice, this is normally a CommonAssemblyInfo.cs file, which holds the assembly attributes shared across all projects in solution, and an AssemblyVersion.cs which is automatically updated by the build process to ensure that assemblies get a version number that matches the TeamCity build number. </li>
<li><strong>ReferencedAssemblies</strong>       <br />Pretty much what it sounds like – external libraries that are used by the solution. These are normally organised into subfolders for each dependency, in order to make it crystal clear which assemblies are part of which dependency – for example, the NHibernate folder contains the core NHibernate.dll, Iesi.Collections and other supporting bits. </li>
<li><strong>RequiredPackages        <br /></strong>Installers for anything you need to set up&#160; locally in order to use some or all of the solution. For example, it helps to have the T4Toolbox installed to work with the T4 templates that are currently part of SA, so the installer for this is included in the RequiredPackages folder of the Sharp-Architecture repository. </li>
<li><strong>Solutions</strong>       <br />Home for the projects that make up the solution. As you’d expect, each project is in it’s own subfolder, and the solution file sits here as well. </li>
</ul>
<p>As mentioned above we felt that a common structure for the repositories is important. Not only does it mean that you know what to expect when getting into each repository, it also facilitates the next major step&#160; &#8211; the creation of a common build system for all of the projects.</p>
<h2>Step 3. Common Build System</h2>
<p>Up until 2.0, Sharp Arch has relied on a Nant build script for build and packaging. This has served well so far, but with the changes we’ve made in the way our repositories are structured, the time was right for a change.</p>
<p>The build system we now have consists of two parts:</p>
<ol>
<li>A set of common MSBuild targets and tasks that encapsulate steps within the build process – for example, building a solution, running unit tests, or packaging source files. These files live in the Sharp-Architecture-Build repository, and each repository contains a submodule that pulls this into the BuildSystem folder. </li>
<li>A script that is specific to each repository and invokes the correct tasks from the common build project, with the correct parameters for the project. This script, along with some batch files that can be used to run it, exists in the Build folder of each repository. </li>
</ol>
<p>Using this set up, and with the knowledge that each repository is structured in the same way, it’s simple to assemble the correct tasks to build and package any of the solutions from the Sharp Architecture repositories. For example, the process to build the Sharp Architecture core solution consists of the following steps:</p>
<ul>
<li>Clean (remove any files from the Drops folder that are about to be recreated by this build)</li>
<li>Update the common assembly version number file that’s shared by all projects.</li>
<li>Build the solution</li>
<li>Run the MSpec unit tests</li>
<li>Merge the assemblies together</li>
<li>Package the assembly and source files.</li>
</ul>
<p>If you compare this with the build process for Northwind – which, given it’s a sample app rather than the framework itself, you might expect to be somewhat different – you’ll see the following steps:</p>
<ul>
<li>Clean</li>
<li>Update the common assembly version number file that’s shared by all projects.</li>
<li>Build the solution</li>
<li>Run the NUnit unit tests</li>
<li>Package the assembly and source files.</li>
</ul>
<p>Clearly the bulk of the steps are actually the same as those required by the core Sharp Arch solution, hence the reason for encapsulating each of these steps in it’s own target so that it can be easily consumed as needed.</p>
<ul><!--EndFragment--></ul>
<p>This system does, unfortunately, add some complexity to the process of getting source from GitHub and building locally. Once you’ve done a <font face="Courier New">git clone</font> of any of the repositories, it’s then necessary to run two additional commands against your clone.</p>
<ul>
<li><font face="Courier New">git submodule init</font> initialises the submodule </li>
<li><font face="Courier New">git submodule update</font> updates the submodule with the files from the correct commit of the Sharp-Architecture-Build repository. </li>
</ul>
<p>Anything that raises the barrier to getting started with Sharp Architecture is clearly not a good thing, so we’re still looking at ways in which this process can be improved.</p>
<p>Once the submodule is up to date, the files in the Build subfolder can then be used to build and package the solution. These scripts are also used for our CI builds, and when used with TeamCity they ensure that the assemblies created and packaged by each build are correctly version stamped with the build number, and that the packages created by the build process are published as build artefacts.</p>
<h2>Next steps</h2>
<p>As we continue working towards 2.0, it’s likely that we’ll evolve what I’ve described here but it’s unlikely to change radically. We’ll probably move to using NuGet instead of the old fashioned way of pulling in external dependencies, which may affect how we use the ReferencedAssemblies folders in each repository. And we’re also not entirely happy with the additional complexity that using Git Submodules adds to the mix, so we’re still thinking of ways to improve this. In addition, we’ll be making some additions to automatically create and publish the Templify and NuGet packages for Sharp Architecture.</p>
<p>As always, we welcome all suggestions, feedback and pull requests so please get involved and help us make Sharp Architecture something you want to use in your projects.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: <a href='http://jonathangeorge.co.uk/tag/build/'>build</a>, <a href='http://jonathangeorge.co.uk/tag/git/'>git</a>, <a href='http://jonathangeorge.co.uk/tag/packaging/'>packaging</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=52&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2011/04/14/making-sharparch-2-0-repositories-build-and-packaging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Static Resource Versioning in IIS7</title>
		<link>http://jonathangeorge.co.uk/2010/01/13/static-resource-versioning-in-iis7/</link>
		<comments>http://jonathangeorge.co.uk/2010/01/13/static-resource-versioning-in-iis7/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 22:45:51 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[iis7]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2010/01/13/static-resource-versioning-in-iis7/</guid>
		<description><![CDATA[A couple of months ago, I blogged about how to improve your YSlow score under IIS7. One of the recommendations from the Yahoo! best practices guide against which YSlow rates your site is that you should set far-future expiry dates for resources such as scripts, images and stylesheets. This is good advice, and straightforward to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=47&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>A couple of months ago, I blogged about <a href="http://jonathangeorge.co.uk/2009/09/09/how-to-improve-your-yslow-score-under-iis7/" target="_blank">how to improve your YSlow score under IIS7</a>. One of the recommendations from the <a href="http://developer.yahoo.com/performance/rules.html">Yahoo! best practices guide</a> against which <a href="http://developer.yahoo.com/yslow/" target="_blank">YSlow</a> rates your site is that you should set far-future expiry dates for resources such as scripts, images and stylesheets.</p>
<p>This is good advice, and straightforward to implement under IIS7, but can leave you with a bit of a problem – once you’ve released your site with all of your scripts and stylesheets set to expire next millenium, you can no longer edit them as you please. If you change them and release them with the same name, returning visitors to your site will not see the changes – they will use the cached version that you told them was good for another 1000 years.</p>
<p>Instead, if you need to change one of your files, you need to give it a new name so that clients who downloaded and cached the original version are sure to get the update when it’s deployed. This means you need to update any references to point to the new file, which has the potential to be a bit of a management nightmare.</p>
<p>Obviously, if you’ve only got one or two of each type of file and you’ve referenced them from a master page or similar shared component then you can handle this manually. However, if you’ve got more than that, or if you’re following the recommendation to combine and pack files, then life can get more fiddly.</p>
<p>On a previous project, I’ve used the <a href="http://www.aptimize.com/" target="_blank">Aptimize Website Accelerator</a>, which handles all this stuff for you in an extremely slick way. However, for projects that don’t use this, I wanted to come up with a way of making the process easier.</p>
<p>In order to do this I decided to take advantage of ASP.NET’s internal URL rewriting feature, exposed via the <a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.rewritepath.aspx" target="_blank">HttpContext.RewritePath</a> method. What I ended up with – which you can <a href="http://jonathangeorge.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=37347" target="_blank">download from Codeplex</a> if you’d like to give it a try – has two parts, the logic to add and remove version numbers from file names and an HttpModule to apply this logic to incoming Urls. The idea is that the code writing out links to the JS/CSS files can pass those filenames through the provider to add a version number, and the HttpModule will intercept incoming requests for those files and rewrite them to point to the correct filename.</p>
<h2>The resourcing versioning provider</h2>
<p>Whilst I’m not a massive fan of the ASP.NET provider model, I’ve recently been feeling the pain of using a variety of different open source projects with overlapping dependencies on different versions of the same tools. I therefore decided to use the provider model to allow me to swap out different ways of generating the version number.</p>
<p>The first important class here is ResourceVersioningProvider. This defines the two methods that providers need to implement.</p>
<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e0369582-8a53-49ae-834b-dce31de8a033" class="wlWriterEditableSmartContent" style="padding:5px;">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">abstract</span> <span style="color:#0000ff;">class</span> <span style="color:#2b91af;">ResourceVersioningProvider</span> : <span style="color:#2b91af;">ProviderBase</span></li>
<li style="background:#f3f3f3;"> {</li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">abstract</span> <span style="color:#0000ff;">string</span> AddVersionNumberToFileName(<span style="color:#0000ff;">string</span> fileName);</li>
<li style="background:#f3f3f3;"></li>
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">abstract</span> <span style="color:#0000ff;">string</span> RemoveVersionNumberFromFileName(<span style="color:#0000ff;">string</span> fileName);</li>
<li style="background:#f3f3f3;"> }</li>
<li></li>
</ol>
</div>
</div>
</div>
<p>It should be pretty obvious what they do from their names.</p>
<p>I’ve then got a base class,  ResourceVersioningProviderBase which contains the code that’s independent of how the version number is generated (basically the filename parsing/modifying logic as well as some caching.) This class is abstract and defines a single abstract method, GetVersionNumber(). This should return the version number that’s going to be used to make the filename unique.</p>
<p>The final relevent class is AssemblyBasedResourceVersioningProvider, which inherits ResourceVersioningProviderBase and implements GetVersionNumber by returning the full version number of an assembly specified in the configuration. The configuration itself looks like this:</p>
<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e8861d1e-825e-41ec-bd82-2938097a1f2c" class="wlWriterEditableSmartContent" style="padding:5px;">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 35px;">
<li> <span style="color:#0000ff;">&lt;</span><span style="color:#a31515;">resourceVersioning</span><span style="color:#0000ff;"> </span><span style="color:#ff0000;">default</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">assemblyVersion</span>&#8220;<span style="color:#0000ff;"> </span><span style="color:#ff0000;">enabled</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">true</span>&#8220;<span style="color:#0000ff;">&gt;</span></li>
<li style="background:#f3f3f3;"> &lt;<span style="color:#a31515;">providers</span><span style="color:#0000ff;">&gt;</span></li>
<li> &lt;<span style="color:#a31515;">add</span><span style="color:#0000ff;"> </span><span style="color:#ff0000;">name</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">assemblyVersion</span>&#8220;<span style="color:#0000ff;"> </span></li>
<li style="background:#f3f3f3;"> <span style="color:#ff0000;">extensionsToVersion</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">.js,.css,.less</span>&#8220;<span style="color:#0000ff;"> </span></li>
<li> <span style="color:#ff0000;">assemblyName</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">WhoCanHelpMe.Web</span>&#8220;<span style="color:#0000ff;"> </span></li>
<li style="background:#f3f3f3;"> <span style="color:#ff0000;">type</span><span style="color:#0000ff;">=</span>&#8220;<span style="color:#0000ff;">Cadenza.Web.ResourceVersioning.AssemblyBasedResourceVersioningProvider,</span></li>
<li> Cadenza.Web.ResourceVersioning&#8221;<span style="color:#0000ff;"> /&gt;</span></li>
<li style="background:#f3f3f3;"> &lt;/<span style="color:#a31515;">providers</span><span style="color:#0000ff;">&gt;</span></li>
<li> &lt;/<span style="color:#a31515;">resourceVersioning</span><span style="color:#0000ff;">&gt;</span></li>
<li style="background:#f3f3f3;"></li>
</ol>
</div>
</div>
</div>
<p>As you can see, there’s also an attribute that controls which file extensions the provider will add version numbers to. This means that if you call “AddVersionToFileName” and pass in an a filename with a different extension, no version number will be added.</p>
<h2>The resource versioning HttpModule</h2>
<p>The HttpModule that forms the other half of the solution is pretty straightforward. Every incoming Url is cracked open using the Uri.Segments property, and the final segment (assumed to be the requested file name) is passed into the provider to remove the version number, if present. If the provider returns a filename that differs from the one in the request url, it is used to build a new Url that can be passed to HttpContext.RewritePath. Processed Urls are cached (regardless of whether or not they require a rewrite) to improve performance.</p>
<h2>In Practice</h2>
<p>The module is in use on the <a href="http://who-can-help.me/" target="_blank">Who Can Help Me?</a> app I introduced in my previous post. If you have a look at the source for the homepage, you’ll see that all the CSS, JavaScript and <a href="http://dotlesscss.com/" target="_blank">DotLess</a> files have the current WhoCanHelpMe.Web assembly version number as part of their name. You can get at <a href="http://whocanhelpme.codeplex.com/" target="_blank">the Who Can Help Me? source via it’s Codeplex site</a> to see how it’s implemented.</p>
<h2>An Alternative Approach</h2>
<p>Despite having written this post a month or so ago, I was only spurred into posting it by reading about <a href="http://codebetter.com/blogs/karlseguin/archive/2010/01/11/asp-net-performance-part-3-cache-busting.aspx" target="_blank">this alternative approach</a> from <a href="http://codebetter.com/blogs/karlseguin/default.aspx" target="_blank">Karl Seguin</a>. He’s got an interesting series going on at the moment covering ASP.NET performance – it’s well worth a read. I can see that it would be fairly straightforward to replace my AssemblyBasedResourceVersioningProvider with a FileHashBasedResourceVersioningProvider, although given that no. 1 on my to do list at the moment is learning  NHibernate, it might be a while before I get round to it!</p>
<p>As I mentioned above, <a href="http://jonathangeorge.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=37347" target="_blank">the compiled assemblies</a> and the source code are available from <a href="http://jonathangeorge.codeplex.com/" target="_blank">my Codeplex site</a>. Please have a play and let me know what you think.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: iis7, performance, yslow <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/47/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=47&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2010/01/13/static-resource-versioning-in-iis7/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Introducing Who Can Help Me? &#8211; A S#arp Architecture Demo Site</title>
		<link>http://jonathangeorge.co.uk/2009/12/21/introducing-who-can-help-me-a-sarp-architecture-demo-site/</link>
		<comments>http://jonathangeorge.co.uk/2009/12/21/introducing-who-can-help-me-a-sarp-architecture-demo-site/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 23:03:57 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[automapper]]></category>
		<category><![CDATA[castle windsor]]></category>
		<category><![CDATA[mspec]]></category>
		<category><![CDATA[nhibernate]]></category>
		<category><![CDATA[postsharp]]></category>
		<category><![CDATA[s#arp architecture]]></category>
		<category><![CDATA[spark]]></category>
		<category><![CDATA[xval]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/12/21/introducing-who-can-help-me-a-sarp-architecture-demo-site/</guid>
		<description><![CDATA[A couple of months ago, myself and some colleagues had the pleasure of pushing the metaphorical big red button and seeing www.fancydressoutfitters.co.uk go live. We all agreed it was one of the best projects we’d worked on in a long time, for a number of reasons. Those reasons can be split into two categories: the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=45&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>A couple of months ago, myself and some colleagues had the pleasure of pushing the metaphorical big red button and seeing <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> go live. We all agreed it was one of the best projects we’d worked on in a long time, for a number of reasons. Those reasons can be split into two categories: the team and the technology.</p>
<p>The core dev team was mostly made up of people who’d worked with one another before. For example I first worked with <a href="http://jamesbroo.me/" target="_blank">James</a> back in 2002, well before either of us joined Conchango (as it then was.) James had spent a lot of time working with <a href="http://howard.vanrooijen.co.uk/blog" target="_blank">Howard</a> on <a href="http://www.tescoentertainment.com/store/browse/mp3/" target="_blank">Tesco Digital</a>, and although I’d never worked with Howard directly I’d had a lot of contact with him on my previous project. We’d all previously worked with Ling (our data architect), Justin (developer, yet to create his own online presence for reasons unknown) and Naz (tester, ditto) on other projects over the previous 3 years. </p>
<p>On most projects, the team spends a fair amount of time up front becoming effective, and a big part of that is getting to know one another – strengths, weaknesses, the way we all communicate and so on. For us, there were only a couple of people that none of us had worked with on previous projects, and that made it simple for the team as a whole to gel really quickly. The process was simplified even further by a great project manager who knew how to make things happen without needing to control the dev team, and a business analyst who managed to take a huge amount of grief from us all about his gratuitous use of clip art in his Powerpoint presentations whilst at the same time winning the respect of the client for the speed with which he understood how they worked internally.</p>
<p>Also, because the team was well resourced up front, Howard and James were able to spend the time laying the appropriate foundations. <a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/10/06/the-importance-of-conventions-from-asp-net-mvc-to-a-successful-project-team.aspx" target="_blank">James has talked about this previously</a>, so I won’t cover it again, but suffice it to say that the time invested up front paid massive dividends later in the project.</p>
<p>The foundations they laid included the core software stack we would use and the tools and techniques we would adopt. They decided that the core of the site would be based on ASP.NET MVC and <a href="http://sharparchitecture.net/" target="_blank">S#arp Architecture</a>, which is a best practice framwork joining MVC with <a href="https://www.hibernate.org/343.html" target="_blank">NHibernate</a>. They also picked some other bits and pieces to reduce friction – things like <a href="http://sparkviewengine.com/" target="_blank">Spark</a>, <a href="http://automapper.codeplex.com/" target="_blank">AutoMapper</a> and <a href="http://xval.codeplex.com/" target="_blank">xVal</a> – and James decided that the project would use <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank">Behaviour Driven Development</a> as a testing approach.</p>
<p>When all of these things came together, one thing that stood out was how clean the resulting solution became. Core design concepts such as <a href="http://c2.com/cgi/wiki?SeparationOfConcerns" target="_blank">separation of concerns</a>, encapsulation and <a href="http://c2.com/cgi/wiki?DependencyInjection" target="_blank">dependency injection</a> were baked in, making the code clean and easy to test. The layers of the solution were well defined and understood, meaning it was always obvious where a particular piece of code should live and it was easy to discuss the codebase between us because we were <a href="http://c2.com/cgi/wiki?UbiquitousLanguage" target="_blank">all talking the same language</a>. The adoption of <a href="http://c2.com/cgi/wiki?BehaviorDrivenDevelopment" target="_blank">BDD</a> finally made using a test-driven approach make sense for those like me who always found it a challenge.</p>
<p>As the project neared it’s end, myself, James and Howard <a href="http://delicious.com/howardvanrooijen/fdo-casestudy?sort=alpha&amp;order=asc" target="_blank">wrote some blog posts talking about various aspects of the solution</a>, but it became hard for all of us to pull out specific bits of code to talk about because removing them from the wider context of the solution caused them to lose their meaning. Howard suggested that we could address this – as well as giving something back to the community that gave us such great software – by putting together an app based on the same architecture and publishing the source code. We could then use it to talk around specific features or areas of the architecture, and at the same time demonstrate to the community the approach we took for the FDO site.</p>
<p>A couple of years back, Howard spent a few hours one evening creating an app called “Who can help me?” Originally intended to capture information about the skills and experience available within Conchango, it took him about 3 hours to put together using ASP.NET WebForms and Linq to SQL. It was the ideal application for our purpose; it has a practical application (we still use it inside EMCC) and it’s simple so the focus can be on the solution design rather than the business logic.</p>
<p>So, <a href="http://who-can-help.me/" target="_blank">here it is: Who Can Help&#160; Me</a>, built using <a href="http://sharparchitecture.net/" target="_blank">S#arp Architecture</a>, <a href="https://www.hibernate.org/343.html" target="_blank">NHibernate</a>, <a href="http://sparkviewengine.com/" target="_blank">Spark View Engine</a>, <a href="http://xval.codeplex.com/" target="_blank">xVal</a>, <a href="http://automapper.codeplex.com/" target="_blank">AutoMapper</a>, <a href="http://www.castleproject.org/container/index.html" target="_blank">Castle Windsor</a>, <a href="http://codebetter.com/blogs/aaron.jensen/archive/2008/05/08/introducing-machine-specifications-or-mspec-for-short.aspx" target="_blank">MSpec</a>, <a href="http://www.ayende.com/projects/rhino-mocks.aspx" target="_blank">RhinoMocks</a> and <a href="http://www.postsharp.org/" target="_blank">PostSharp</a>. We’ve pulled in some new bits, such as MEF and <a href="http://www.ohloh.net/p/dotnetopenauth" target="_blank">DotNetOpenAuth</a>, hooked it up to Twitter using <a href="http://tweetsharp.com/" target="_blank">TweetSharp</a> to demonstrate the pattern for external service integration, and <a href="http://whocanhelpme.codeplex.com/" target="_blank">published the whole lot on Codeplex</a>.</p>
<p>The result is definitely more complex than the problem requires, but that’s ok – as I mentioned above, we specifically chose a simple application to demonstrate an enterprise level architectural approach with the hope that the focus could be on the latter. So <a href="http://who-can-help.me/" target="_blank">please have a play with the live site</a>, download the code, give it the once over and let us know what you think. We’ll be blogging about the bits we find interesting (links below), as well as tidying up the bits we’re not so keen on and we’d love to hear any feedback you have.</p>
<ul>
<li><a href="http://jonathangeorge.co.uk/">Jonathan George</a> &#8211; <a href="http://twitter.com/jon_george1">@jon_george1</a> </li>
<li><a href="http://howard.vanrooijen.co.uk/blog">Howard van Rooijen</a> &#8211; <a href="http://twitter.com/HowardvRooijen">@HowardvRooijen</a> </li>
<li><a href="http://jamesbroo.me/">James Broome</a> &#8211; <a href="http://twitter.com/broomej">@broomej</a> </li>
</ul>
<p>We’ll also be using the <a href="http://twitter.pbworks.com/Hashtags" target="_blank">hashtag</a> <a href="http://twitter.com/#search?q=%23wchm" target="_blank">#WCHM on Twitter</a> when we talk about this, so keep an eye out.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net, asp.net mvc, automapper, castle windsor, mspec, nhibernate, postsharp, s#arp architecture, spark, xval <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/45/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=45&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/12/21/introducing-who-can-help-me-a-sarp-architecture-demo-site/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>New blog site</title>
		<link>http://jonathangeorge.co.uk/2009/11/19/new-blog-site/</link>
		<comments>http://jonathangeorge.co.uk/2009/11/19/new-blog-site/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 15:34:31 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/11/19/new-blog-site/</guid>
		<description><![CDATA[Welcome to my new blog. I started blogging a few months ago at http://consultingblogs.emc.com/jonathangeorge/ and I intend to continue here. I’ll mainly be blogging about the things I do in my day to day job as a technical consultant. Over the past few years this has primarily been developing e-commerce sites using ASP.NET, and more [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=11&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Welcome to my new blog. I started blogging a few months ago at <a title="http://consultingblogs.emc.com/jonathangeorge/" href="http://consultingblogs.emc.com/jonathangeorge/">http://consultingblogs.emc.com/jonathangeorge/</a> and I intend to continue here. </p>
<p>I’ll mainly be blogging about the things I do in my day to day job as a technical consultant. Over the past few years this has primarily been developing e-commerce sites using ASP.NET, and more recently ASP.NET MVC – have a look at <a href="http://www.fancydressoutfitters.co.uk/" target="_blank">FancyDressOutfitters.co.uk</a> for the most recent result. I have a strong interest in using sound engineering practices in my projects – continuous integration, test or behaviour driven development, to name a couple – as well as using lean techniques to deliver those projects.</p>
<p>I always welcome feedback, so please tell me what you think of my posts by leaving a comment or <a href="http://twitter.com/jon_george1" target="_blank">via Twitter</a>.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/11/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=11&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/11/19/new-blog-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Optimising an ASP.NET MVC web site, part 5: Putting your money where your mouth is</title>
		<link>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-5-putting-your-money-where-your-mouth-is/</link>
		<comments>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-5-putting-your-money-where-your-mouth-is/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 17:51:00 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[n2cms]]></category>
		<category><![CDATA[nhibernate]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[s#arp architecture]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[spark]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/11/03/optimising-an-asp-net-mvc-web-site-part-5-putting-your-money-where-your-mouth-is/</guid>
		<description><![CDATA[Note: This was originally posted on my old blog at the EMC Consulting Blogs site. This is the final part of a series of posts on optimisation work we carried out on my last project, www.fancydressoutfitters.co.uk – an ASP.NET MVC web site built using S#arp Architecture, NHibernate, the Spark view engine and Solr. There’s not [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=27&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>Note: This was originally posted on </strong><a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"><strong>my old blog</strong></a><strong> at the </strong><a href="http://consultingblogs.emc.com/"><strong>EMC Consulting Blogs site</strong></a><strong>.</strong></p>
<p><i>This is the final part of a series of posts on optimisation work we carried out on my last project, <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> – an ASP.NET MVC web site built using </i><a href="http://code.google.com/p/sharp-architecture/"><i>S#arp Architecture</i></a><i>, </i><a href="https://www.hibernate.org/343.html"><i>NHibernate</i></a><i>, the </i><a href="http://sparkviewengine.com/"><i>Spark view engine</i></a><i> and </i><a href="http://lucene.apache.org/solr/"><i>Solr</i></a><i>. There’s not much point starting here – please have a look at parts <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-1-introduction/">1</a>, <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/">2</a>, <a href="http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/">3</a> and <a href="http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-4-output-caching-in-the-brave-new-world-of-mvc/" target="_blank">4</a>, as well as <a href="http://jonathangeorge.co.uk/2009/09/09/how-to-improve-your-yslow-score-under-iis7/">my post on improving YSlow scores for IIS7 sites</a>, for the full picture.</i></p>
<p>In the posts on this series, I’ve reflected the separation of concerns inherent in ASP.NET MVC applications by talking about how we optimised each layer of the application independently. Good separation of concerns is by no means unique to applications built using the MVC pattern, but what stood out for me as I became familiar with the project was that for the first time it seemed like I hardly had to think to achieve it, because it’s so baked into the framework. I know I share this feeling with <a href="http://consultingblogs.emc.com/howardvanrooijen/default.aspx" target="_blank">Howard</a> and <a href="http://consultingblogs.emc.com/jamesbroome/" target="_blank">James</a> (respectively architect and developer on the project), who’ve both talked about it in their own blogs.</p>
<p>The MVC pattern also makes it much easier to apply optimisations in the code. For example, it’s much easier to identify the points where caching will be effective, as the Model-View-ViewModel pattern makes it straightforward to apply a <a href="http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/" target="_blank">simple and highly effective caching pattern</a> within the controllers. I know that this kind of thing isn’t limited to performance work – for example, our team security guru certainly felt that it was easier to carry out his threat modelling for this site than it would have been in a WebForms equivalent.</p>
<p>On the flip side, this process also brought home to me some of the dangers of using NHibernate. It’s an absolutely awesome product, and has totally converted me to the use of an ORM (be it NHib or Entity Framework). However, the relatively high learning curve and the fact that most of the setup was done before I joined the project made it easy for me to ignore what it was doing under the covers and code away against my domain objects in a state of blissful ignorance. Obviously this is not a brilliant idea, and properly getting to grips with NH it now jostling for first place on my to-do list (up against <a href="http://www.postsharp.org/" target="_blank">PostSharp 2</a> and <a href="http://haacked.com/archive/2009/10/01/asp.net-mvc-preview-2-released.aspx" target="_blank">ASP.NET MVC 2.0</a>, amongst other things.)</p>
<p>My big challenge for future projects is ensuring that the optimisations I’ve talked about are baked in from the start instead of being bolted on at the end. The problem with this is that it’s not always clear where to stop. The goal of optimising the site is to get it to the point where it performs as we need it to, not to get it to the point where we can’t optimise any more. The process of optimisation is one of diminishing returns, so it’s essential to cover issues you know need to be covered and to then use testing tools to uncover any further areas to work on.</p>
<p>That said, in an ideal world I’d like to be able to build performance tests early and use them to benchmark pages on a regular basis. Assuming you work in short iterations, this can be done on an iteration by iteration basis, with results feeding into the plan for the next iteration. My next series of posts will be on performance and load testing, and as well as covering what we did for this project I will be looking at ways of building these processes into the core engineering practices of a project.</p>
<h2>Was it all worth it?</h2>
<p>I’ll be talking separately about the performance and load testing we carried out on the site prior to go live, but in order to put these posts into some context I thought it might be interesting to include some final numbers. For our soak testing, we built a load profile based on 6 user journeys through the site:</p>
<ul>
<li>Homepage: 20% of total concurrent user load </li>
<li>Browse (Home -&gt; Category Landing -&gt; Category Listing -&gt; Product): 30% </li>
<li>Search (Home -&gt; Search Results): 30% </li>
<li>News (Home -&gt; News list -&gt; News story): 10% </li>
<li>Static Pages (Home -&gt; Static page): 5% </li>
<li>Checkout (As for browse journey, then -&gt; Add to basket -&gt; View Basket -&gt; Checkout): 5% </li>
</ul>
<p>With a random think time of 8 – 12 seconds between each step of each journey, we demonstrated that each of the web servers in the farm could sustainably support 1000 concurrent users and generate 90 pages per second. Given the hardware in question, this far exceeds any project I’ve worked on recently.</p>
<p>In the end, we put <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> live in the run up to Halloween, the busiest time of the year for the fancy dress industry. We did this with no late nights and enough confidence to go to the pub for a celebratory pint within the hour. It was also interesting that the majority of technical colleagues who responded to our go-live announcement commented on how fast it runs (which given the machinations of our corporate network’s internet routing is even more remarkable.) And best of all, we’ve had no major shocks since the site went live.</p>
<h2>A final note</h2>
<p>If you’ve read this series of posts, I hope you’ve got something out of it. I’d certainly be interested in any feedback that you might have – as always, please feel free to leave a comment or contact me on <a href="http://twitter.com/jon_george1" target="_blank">Twitter</a>.&#160; In addition, the EMC Consulting blog site has been nominated in the <a href="http://www.computerweekly.com/Articles/2009/09/14/237679/it-blog-awards-2009-name-your-favourite-blogger.htm" target="_blank">Computer Weekly IT Blog Awards 2009</a>, under the <a href="http://www.computerweekly.com/Articles/2009/09/20/237826/it-blog-awards-2009-company-corporate-large-enterprise.htm" target="_blank">“Corporate/Large Enterprise” category</a> – please consider <a href="http://www.computerweekly.com/Articles/2009/11/03/238190/vote-in-the-computer-weekly-it-blog-awards-2009.htm" target="_blank">voting for us</a>.</p>
<p>I’d also like to extend a final thanks to <a href="http://consultingblogs.emc.com/howardvanrooijen/default.aspx" target="_blank">Howard</a> for proof reading the first draft of these posts and giving me valuable feedback, as well as for actually doing a lot of the work I’ve talked about here.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net, asp.net mvc, n2cms, nhibernate, performance, s#arp architecture, solr, spark <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/27/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=27&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-5-putting-your-money-where-your-mouth-is/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Optimising an ASP.NET MVC web site, part 4: Output caching in the brave new world of MVC</title>
		<link>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-4-output-caching-in-the-brave-new-world-of-mvc/</link>
		<comments>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-4-output-caching-in-the-brave-new-world-of-mvc/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 16:11:00 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[s#arp architecture]]></category>
		<category><![CDATA[spark]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/10/12/optimising-an-asp-net-mvc-web-site-part-4-output-caching-in-the-brave-new-world-of-mvc/</guid>
		<description><![CDATA[Note: This was originally posted on my old blog at the EMC Consulting Blogs site. This is the penultimate part in a series of posts on optimisation work we carried out on my last project, www.fancydressoutfitters.co.uk – an ASP.NET MVC web site built using S#arp Architecture, NHibernate, the Spark view engine and Solr. Please also [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=25&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>Note: This was originally posted on </strong><a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"><strong>my old blog</strong></a><strong> at the </strong><a href="http://consultingblogs.emc.com/"><strong>EMC Consulting Blogs site</strong></a><strong>.</strong></p>
<p><em>This is the penultimate part in a series of posts on optimisation work we carried out on my last project, <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> – an ASP.NET MVC web site built using </em><a href="http://code.google.com/p/sharp-architecture/"><em>S#arp Architecture</em></a><em>, </em><a href="https://www.hibernate.org/343.html"><em>NHibernate</em></a><em>, the </em><a href="http://sparkviewengine.com/"><em>Spark view engine</em></a><em> and </em><a href="http://lucene.apache.org/solr/"><em>Solr</em></a><em>. Please also take the time to read parts <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-1-introduction/" target="_blank">1</a>, <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/" target="_blank">2</a> and <a href="http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/" target="_blank">3</a> for the full picture.</em></p>
<p>Output caching is something I’ve used extensively on previous ASP.NET WebForm projects, and I was surprised when I found out that it’s relatively immature in ASP.NET MVC. The core library contains the <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.outputcacheattribute.aspx" target="_blank">OutputCache</a> filter, which does the same under the covers as the <a href="http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx" target="_blank">@OutputCache</a> declaration in ASP.NET Web Forms. However, caching a full page is something that rarely suits in the current climate of dynamic and personalised websites – for example (and in common with most ecommerce websites) our site includes a summary of the user’s basket on every page. In the world of web forms, I’d use the <a href="http://weblogs.asp.net/scottgu/archive/2006/11/28/tip-trick-implement-donut-caching-with-the-asp-net-2-0-output-cache-substitution-feature.aspx" target="_blank">asp:substitution control to implement donut caching</a>, or implement <a href="http://support.microsoft.com/kb/308378" target="_blank">fragment caching</a>. Unfortunately neither of those options exist in the brave new world of ASP.NET MVC (if you’re a Java/Ruby/etc developer… stop sniggering, we’re catching you up <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ) </p>
<p>So there are a few ways round this that I’m aware of. The first involves using the partial views to do something similar to the old style ASP.NET Fragment Caching approach. In the WebForms world, this is implemented by splitting your page up into multiple user controls, and applying output caching as appropriate to the individual controls. Here’s a pretty basic example of how a product page on an ecommerce website might be laid out.</p>
<p><img style="display:block;float:none;margin-left:auto;margin-right:auto;border-width:0;" title="Page layout" border="0" alt="Page layout" src="http://jonathangeorge.files.wordpress.com/2009/11/pagelayout.png?w=527&#038;h=318" width="527" height="318" /> </p>
<p>The boxes coloured blue, green and purple can all be cached – albeit with different cache lifetimes and keys. The red box, which displays my user&#160; basket total is unlikely to be cachable – at least not at the rendering level. Using the classic ASP.NET fragment caching approach, each of my coloured boxes would be implemented as a separate user control with appropriate OutputCache directives set. The ASPX page itself would contain very little other than the instances of these controls.</p>
<p>So how does this translate into MVC? It turns out that it’s pretty much the same. You create a number of partial views and add an OutputCache directive to their markup. Phil Haack <a href="http://haacked.com/archive/2009/05/12/donut-hole-caching.aspx" target="_blank">covers the approach in this blog post.</a> There’s just one downside: that approach only works with the standard WebForms view engine, and we’re using Spark, so we can’t go down this route.</p>
<p>I did hear a suggestion that making use of the RenderAction method from ASP.NET MVC 1.0 Futures could be the way forward. Essentially, each of my coloured boxes from the diagram would end up corresponding to a separate controller action, each of which would have an OutputCache action filter applied. These would then be pulled together by a “dumb” controller action whose corresponding view had multiple calls to Html.RenderAction to compose the chunks of the view together.</p>
<p>On the face of it – and assuming you were willing to accept the overhead involved in repeatedly invoking the full MVC request pipeline – it would work. However, there has been <a href="http://stackoverflow.com/questions/606962/outputcache-and-renderaction-cache-whole-page" target="_blank">mention of a bug with MVC 1.0</a> which causes the OutputCache filter on an action method called with RenderAction to be applied to the overall request, not just the chunk being dealt with. This kind of thing is probably why the RenderAction method was bumped into MVC Futures instead of being shipped as part of the core MVC 1.0 release.</p>
<p>Phil Haack <a href="http://haacked.com/archive/2008/11/05/donut-caching-in-asp.net-mvc.aspx" target="_blank">blogged something else that didn’t quite make it to MVC 1.0</a> which looked good on the surface. Essentially, it’s an HtmlHelper extension that hooks into the API used by the asp:substitution control. However, I had a bit of a headache in trying to work out how to use it. The problem is that within the callback you supply to the Substitute method, you don’t have access to your ViewData – not a massive surprised once you understand how the post-cache substitution mechanism in ASP.NET works. This means that you need to code some other method – which is going to be a static method you’ve stashed alongside your controllers – that will do all the necessary work, pulling bits of data out of the supplied HttpContext and returning a string to be dumped directly into the view.</p>
<p>There’s no doubt that this would work, and with some thought could be done without losing the testability and separation of concerns that makes the MVC pattern great. However, it’s not an ideal approach for me because it does mean that the pattern and conventions are broken to support what’s essentially an optimisation step. Because of this it will make it harder for people to see what’s going on in the code. I’ve already covered the caching we applied in the service layer; to me, output caching should be contained within the View Engine layer and should not leak beyond that. After all, there’s nothing else in my controller layer or below that couples my code to Spark, so I have no desire to introduce something that does.</p>
<p>Fortunately it turns out that the <a href="http://sparkviewengine.com/documentation/caching" target="_blank">1.1 version of the Spark view engine will contain pretty comprehensive output caching</a>. This isn’t part of the v1.0 release, but has been in the development builds for several months now and is stable. It’s absolutely perfect for what I wanted as it allowed me to implement output caching with very few changes outside the views.</p>
<p>Unlike the ASP.NET WebForms fragment caching approach, you aren’t required to split your view into partials – you simply add &lt;cache&gt; elements around the sections of the page you want to cache. These sections can be dependent on different keys and cached for different durations, and there’s also a <a href="http://sparkviewengine.com/documentation/caching#Signalingdependentdatachanged" target="_blank">signalling mechanism</a> that allows cached content to be expired on demand. In our case, we had already tackled the issue of cache keys for a ViewModels when we looked at <a href="http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/" target="_blank">caching in the controller layer</a>, so it was a simple matter to use these same cache keys to control our output caching.</p>
<p>Spark also contains something called the <a href="http://sparkviewengine.com/documentation/caching#UsingValueHolderforcleanviews" target="_blank">ValueHolder</a> which effectively allows you to defer the gathering of model data until it’s needed. This means that rather than build up the model for every request, only to pass it to a view which doesn’t need it because it’s entirely output cached, you can build your model using ValueHolder objects containing lambda functions that will only be executed if the data is needed. This seems like an interesting approach, but it’s not one I explored in detail because the caching we’d already implemented on the controllers made it less relevant.</p>
<p>One of my major hopes, which was unfortunately not realised, was that we’d be able to connect Spark’s output caching service to our distributed cache, <a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx" target="_blank">Velocity</a>. This would further reduce the workload across the web farm because it would mean that once a page was served from one webhead, it would be available pre-built to all of the others. However the output caching mechanism in Spark places unserializable objects into the cache, making it difficult to use with an out-of-process caching mechanism. This is a shame but by no means a deal breaker.</p>
<p>I’ve seen a few discussions around the value of output caching in the MVC world, with some saying that because the views are essentially just writing text to a stream, there is little gain to be had from caching. On a purely subjective level, the output caching did seem to make the site faster. It’s difficult to be sure because there is no way of enabling/disabling output caching via config in Spark, so it’s not easy to do comparative tests in a realistic environment. I can see the argument, and I’d certainly agree that out of the different focus areas output caching made the least difference to overall performance, but I believe it did make a difference and for the minimal effort involved in implementing it, was worth it.</p>
<p>In the final section, I’ll talk about my views on optimising this MVC based site compared to my experiences in the WebForms world, and share some hard numbers gained from our performance testing.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net, asp.net mvc, performance, s#arp architecture, spark <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/25/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/25/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=25&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/11/03/optimising-an-asp-net-mvc-web-site-part-4-output-caching-in-the-brave-new-world-of-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>

		<media:content url="http://jonathangeorge.files.wordpress.com/2009/11/pagelayout.png" medium="image">
			<media:title type="html">Page layout</media:title>
		</media:content>
	</item>
		<item>
		<title>Using an alternative ITempDataProvider implementation in ASP.NET MVC</title>
		<link>http://jonathangeorge.co.uk/2009/10/14/using-an-alternative-itempdataprovider-implementation-in-asp-net-mvc/</link>
		<comments>http://jonathangeorge.co.uk/2009/10/14/using-an-alternative-itempdataprovider-implementation-in-asp-net-mvc/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 12:47:00 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[dependency injection]]></category>
		<category><![CDATA[velocity]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/10/14/using-an-alternative-itempdataprovider-implementation-in-asp-net-mvc/</guid>
		<description><![CDATA[Note: This was originally posted on my old blog at the EMC Consulting Blogs site. As I’ve previously mentioned, we’re using Microsoft Velocity as the caching provider on my current project. One of my recent tasks was to create a new implementation of ITempDataProvider that stored data in the Velocity cache instead of Session State. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=28&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>Note: This was originally posted on </strong><a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"><strong>my old blog</strong></a><strong> at the </strong><a href="http://consultingblogs.emc.com/"><strong>EMC Consulting Blogs site</strong></a><strong>.</strong></p>
<p>As I’ve previously mentioned, we’re using <a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx" target="_blank">Microsoft Velocity</a> as the caching provider on my current project. One of my recent tasks was to create a new implementation of <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.itempdataprovider.aspx" target="_blank">ITempDataProvider</a> that stored data in the Velocity cache instead of Session State.</p>
<p>Now, I’m aware that a potentially faster implementation would have been to use the Velocity Session State provider, but when I tried this I hit a few snags. Basically, when you use Velocity directly, objects you add to the cache are serialized using the <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx" target="_blank">DataContractSerializer</a> from the System.Runtime.Serialization namespace. This is nice because it means you don’t need to mark all your objects with the Serializable attribute, or start implementing ISerializable – as described <a href="http://msdn.microsoft.com/en-us/library/ms731923.aspx" target="_blank">here</a>, the DataContractSerializer is capable of serializing objects of any public type that has a parameterless constructor. However, when you use Velocity’s session state provider, the framework takes over and you uses the more restrictive <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx" target="_blank">BinaryFormatter</a> from the System.Runtime.Serialization.Formatters.Binary namespace. This does require you to explicitly make your objects serializable, which is a bit of a pain.</p>
<p>To avoid going through and marking the relevant classes serializable, I took the plunge and knocked up an ITempDataProvider implementation using Velocity for my project. It was actually a very straightforward task, but once I’d done that my next issue was to work out how to get it into my controllers. </p>
<p>The examples I’ve seen online suggest one of two approaches:</p>
<ol>
<li>Initialise it in either the constructor or the Initialize() method of the base controller. </li>
<li>Set it in the controller factory. </li>
</ol>
<p>Option 1 would look something like this:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e088b0c0-718c-4107-8000-22ac7ba582db" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#0000ff;">public</span> BaseController()</li>
<li style="background:#f3f3f3;"> {</li>
<li>     <span style="color:#0000ff;">this</span>.TempDataProvider = <span style="color:#0000ff;">new</span> VelocityTempDataProvider();</li>
<li style="background:#f3f3f3;"> }</li>
<li> </li>
</ol>
</div>
</div>
</div>
<p>Simple enough, however all my controllers would instantly be tightly coupled to the VelocityTempDataProvider. Ok, so in my tests I could set the TempDataProvider property to a mock straight after creation of the controller, but it’s still not nice.</p>
<p>I could do this:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:ddbded23-761b-4d2d-ba73-cc4af69ab91a" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#0000ff;">public</span> BaseController()</li>
<li style="background:#f3f3f3;"> {</li>
<li> }</li>
<li style="background:#f3f3f3;"> </li>
<li> <span style="color:#0000ff;">public</span> BaseController(<span style="color:#2b91af;">ITempDataProvider</span> tempDataProvider)</li>
<li style="background:#f3f3f3;"> {</li>
<li>     <span style="color:#0000ff;">this</span>.TempDataProvider = tempDataProvider;</li>
<li style="background:#f3f3f3;"> }</li>
<li> </li>
</ol>
</div>
</div>
</div>
<p>Which would also work, although it would require all derived controllers to pass the required instance of ITempDataProvider through from their own constructors, requiring me to modify all of the derived classes. Or there’s this:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f97c11a7-c805-46d0-bfef-53ca7a00d66d" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#0000ff;">public</span> BaseController() : <span style="color:#0000ff;">this</span>(<span style="color:#0000ff;">new</span> VelocityTempDataProvider())</li>
<li style="background:#f3f3f3;"> {</li>
<li> }</li>
<li style="background:#f3f3f3;"> </li>
<li> <span style="color:#0000ff;">public</span> BaseController(<span style="color:#2b91af;">ITempDataProvider</span> tempDataProvider)</li>
<li style="background:#f3f3f3;"> {</li>
<li>     <span style="color:#0000ff;">this</span>.TempDataProvider = tempDataProvider;</li>
<li style="background:#f3f3f3;"> }</li>
<li> </li>
</ol>
</div>
</div>
</div>
<p>Which will default all controllers to use the Velocity temp data provider unless they specify an alternative.</p>
<p>Ultimately though, I don’t like the fact that Option 1 requires selecting the correct ITempDataProvider implementation in the controllers themselves. All of these methods would work, but setting the TempDataProvider property is a responsibility that fits better in the controller factory than the controller itself. The factory is responsible for building the controller; it should be responsible for setting up any dependencies at the same time.</p>
<p>We’re using the WindsorControllerFactory from <a href="http://www.codeplex.com/MVCContrib" target="_blank">MvcContrib</a> to allow <a href="http://www.castleproject.org/container/index.html" target="_blank">Castle Windsor</a> to create our controllers and automagically resolve their dependencies for us. As part of our application startup, we execute this code:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:119e6829-22ff-41f1-9f39-5cbff58f91a9" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#2b91af;">ControllerBuilder</span>.Current.SetControllerFactory(<span style="color:#0000ff;">new</span> <span style="color:#2b91af;">WindsorControllerFactory</span>(<span style="color:#0000ff;">this</span>.container));</li>
</ol>
</div>
</div>
</div>
<p>This is what tells the MVC framework to use the Windsor controller factory. So what’s the best way of getting my custom temp data provider in there? I could subclass the WindsorControllerFactory and override the relevant methods. But using a custom temp data provider isn’t something I’d only ever want to do with WindsorControllerFactory – it could equally apply to the default controller factory, or to any other.</p>
<p>It’s a scenario that could be custom made for what I think is my favourite <a href="http://c2.com/cgi/wiki?GangOfFour" target="_blank">Gang of Four</a> design pattern: decorator. This pattern allows you to compose additional responsibilities onto an object without needing to subclass it. If you’re not familiar with it, I’d suggest a read of <a href="http://oreilly.com/catalog/hfdesignpat/chapter/ch03.pdf" target="_blank">this chapter</a> from the <a href="http://www.amazon.co.uk/Head-First-Design-Patterns-Freeman/dp/0596007124" target="_blank">Head First Design Patterns</a> book.</p>
<p>Here’s what my decorator looks like:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:502db8d6-b776-48f1-819f-0fc9a58f6b10" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 35px;">
<li> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> <span style="color:#2b91af;">ControllerFactoryCustomTempDataProviderDecorator</span> : IControllerFactory</li>
<li style="background:#f3f3f3;"> {</li>
<li>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> IControllerFactory decoratedControllerFactory;</li>
<li style="background:#f3f3f3;"> </li>
<li>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> IWindsorContainer windsorContainer;</li>
<li style="background:#f3f3f3;"> </li>
<li>     <span style="color:#0000ff;">public</span> ControllerFactoryCustomTempDataProviderDecorator(IControllerFactory decoratedControllerFactory, IWindsorContainer container)</li>
<li style="background:#f3f3f3;">     {</li>
<li>         <span style="color:#0000ff;">this</span>.decoratedControllerFactory = decoratedControllerFactory;</li>
<li style="background:#f3f3f3;">         <span style="color:#0000ff;">this</span>.container = container;</li>
<li>     }</li>
<li style="background:#f3f3f3;"> </li>
<li>     <span style="color:#0000ff;">public</span> IController CreateController(RequestContext requestContext, <span style="color:#0000ff;">string</span> controllerName)</li>
<li style="background:#f3f3f3;">     {</li>
<li>         <span style="color:#0000ff;">var</span> controller = <span style="color:#0000ff;">this</span>.decoratedControllerFactory.CreateController(</li>
<li style="background:#f3f3f3;">             requestContext, </li>
<li>             controllerName);</li>
<li style="background:#f3f3f3;"> </li>
<li>         <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">this</span>.SetTempDataProvider(controller);</li>
<li style="background:#f3f3f3;">     }</li>
<li> </li>
<li style="background:#f3f3f3;">     <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> ReleaseController(IController controller)</li>
<li>     {</li>
<li style="background:#f3f3f3;">         <span style="color:#0000ff;">this</span>.decoratedControllerFactory.ReleaseController(controller);</li>
<li>     }</li>
<li style="background:#f3f3f3;"> </li>
<li>     <span style="color:#0000ff;">private</span> IController SetTempDataProvider(IController controller)</li>
<li style="background:#f3f3f3;">     {</li>
<li>         <span style="color:#0000ff;">var</span> concreteController = controller <span style="color:#0000ff;">as</span> Controller;</li>
<li style="background:#f3f3f3;">         </li>
<li>         <span style="color:#0000ff;">if</span> (concreteController != <span style="color:#0000ff;">null</span>)</li>
<li style="background:#f3f3f3;">         {</li>
<li>             concreteController.TempDataProvider = <span style="color:#0000ff;">this</span>.windsorContainer.Resolve&lt;ITempDataProvider&gt;();</li>
<li style="background:#f3f3f3;">         }</li>
<li> </li>
<li style="background:#f3f3f3;">         <span style="color:#0000ff;">return</span> controller;</li>
<li>     }</li>
<li style="background:#f3f3f3;"> \</li>
</ol>
</div>
</div>
</div>
<p>And here’s how it’s used:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b7c3e6cd-d9f8-4d72-98aa-d53a731dde3a" class="wlWriterEditableSmartContent">
<div style="border:#000080 1px solid;font-family:'Courier New', Courier, Monospace;font-size:10pt;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;white-space:wrap;margin:0 0 0 25px;">
<li> <span style="color:#0000ff;">var</span> windsorContollerFactory = <span style="color:#0000ff;">new</span> <span style="color:#2b91af;">WindsorControllerFactory</span>(<span style="color:#0000ff;">this</span>.container);</li>
<li style="background:#f3f3f3;"> <span style="color:#0000ff;">var</span> decoratedControllerFactory =</li>
<li>     <span style="color:#0000ff;">new</span> <span style="color:#2b91af;">ControllerFactoryCustomTempDataProviderDecorator</span></li>
<li style="background:#f3f3f3;">         (windsorContollerFactory, </li>
<li>         <span style="color:#0000ff;">this</span>.container);</li>
<li style="background:#f3f3f3;"> </li>
<li> <span style="color:#2b91af;">ControllerBuilder</span>.Current.SetControllerFactory(decoratedControllerFactory);</li>
<li style="background:#f3f3f3;"> </li>
</ol>
</div>
</div>
</div>
<p>So now all my controllers will have their TempDataProvider property set at the time of creation. As an added bonus, the specific implementation of ITempDataProvider to use is also resolved using the Windsor container making it easily configurable.</p>
<p>I’m a lot happier with the design I’ve ended up with – it’s more flexible and reusable and it doesn’t annoy me every time I see it. Of course, any of the other methods I mentioned would have worked, and other people might prefer them, but I hope this has given you a few options to consider if you need to do something similar.</p>
<p><strong>Update (later that same day…)</strong></p>
<p>Writing this up must have re-awoken some thought processes because as I was making my way home I started wondering again about my final solution. My thought process went something like this:</p>
<ol>
<li>I created a decorator with the sole purpose of setting a property of my controllers. Basically, it’s job is to inject a dependency into a newly created object. </li>
<li>I am using a dependency injection tool (Castle Windsor) to create my controllers. </li>
<li>Why am I not using my dependency injection tool to inject my dependency? </li>
</ol>
<p>Why indeed?</p>
<p>Ever since I started using Windsor, I’ve used constructor injection for dependencies – that way you don’t have to tell it which dependencies you need it to resolve, it will just do it’s best to satisfy all the constructor arguments from the types it has registered. But like all good IoC containers, Windsor also supports property setter injection – essentially, I can tell it to set properties on newly created objects to whatever I want them set to. (See <a href="http://martinfowler.com/articles/injection.html#ConstructorVersusSetterInjection" target="_blank">this article</a> for more details.)</p>
<p>So the decorator I was happy with last week is now redundant. That doesn’t mean it wouldn’t ever be useful – it could easily be used with the standard ASP.NET MVC controller factory, for example. However, for any controller factory that uses an IOC container it is probably not needed.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net mvc, dependency injection, velocity <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/28/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/28/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=28&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/10/14/using-an-alternative-itempdataprovider-implementation-in-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Optimising an ASP.NET MVC web site, part 3: Application Caching</title>
		<link>http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/</link>
		<comments>http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 21:46:00 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[s#arp architecture]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/</guid>
		<description><![CDATA[Note: This was originally posted on my old blog at the EMC Consulting Blogs site. This is part 3 in a series of posts on optimisation work we carried out on my current project, www.fancydressoutfitters.co.uk – an ASP.NET MVC web site built using S#arp Architecture, NHibernate, the Spark view engine and Solr. Please see&#160; part [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=23&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>Note: This was originally posted on </strong><a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"><strong>my old blog</strong></a><strong> at the </strong><a href="http://consultingblogs.emc.com/"><strong>EMC Consulting Blogs site</strong></a><strong>.</strong></p>
<p><i>This is part 3 in a series of posts on optimisation work we carried out on my current project, <a href="http://www.fancydressoutfitters.co.uk">www.fancydressoutfitters.co.uk</a> – an ASP.NET MVC web site built using <a href="http://code.google.com/p/sharp-architecture/" target="_blank">S#arp Architecture</a>, <a href="https://www.hibernate.org/343.html" target="_blank">NHibernate</a>, the <a href="http://sparkviewengine.com/" target="_blank">Spark view engine</a> and <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a>. Please see&#160; <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-1-introduction/">part 1</a> and <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/">part 2</a> for the background.</i></p>
<p>I doubt many people will disagree with me when I say that one sure-fire way of making a piece of code run faster and consume less of your precious processing power is to do less work in that piece of code. Optimising your code is part of the answer, but however quickly your pages run when it’s just you on the site you will struggle to serve large numbers of users unless you have a good caching strategy in place.</p>
<p>There are a number of places that caching can be applied in an application built using S#arp Architecture. Here are a few:</p>
<ul>
<li>You can use the NHibernate second-level cache to store the results of database queries. </li>
<li>You can apply caching wherever it’s appropriate in your model layer. </li>
<li>You can cache the results of controller actions; and </li>
<li>You can apply output caching to the rendered views (to be covered in part 4). </li>
</ul>
<p>However the whole thing is something of a balancing act. You have to understand how often things are going change and weigh up the benefits of longer caching durations against the need to reflect updates in a timely fashion. You need to understand how your platform architecture affects your caching strategy – for example, what happens if you have multiple web servers each maintaining it’s own local cache? You also need to make sure that once you’ve decided on an approach, people stick to it. I’ve never been a big fan of using the standard HTTP Cache directly – it requires you to specify the caching interval every time you add an object to the cache. Even if you implement some constants to hold the intervals, you still run the risk of people choosing the wrong one.</p>
<h2>How we approach caching</h2>
<p>Both my current S#arp Architecture-based project and my previous WebForms one make extensive use of Dependency Injection to decouple our assemblies and increase testability. It follows that we needed to create an abstraction for the cache anyway, so we took the opportunity to kill two birds with one stone and introduce a more convention-based approach to the cache. <a href="http://consultingblogs.emc.com/jamesbroome/" target="_blank">James</a> has recently blogged about <a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/10/06/the-importance-of-conventions-from-asp-net-mvc-to-a-successful-project-team.aspx" target="_blank">the benefits of removing decisions from our day-to-day coding activities</a>, and this is another example. In our abstraction, we treat the cache as a set of named areas and assign cache duration to those areas instead of to the individual objects. A few examples of the named areas we use are:</p>
<ul>
<li>Content – medium lifespan, intended for content pulled from the CMS; </li>
<li>Resources – very long lifespan, containing values from our SQL-based resource provider (used instead of the standard RESX file-based provider); and </li>
<li>Site Furniture – long lifespan, containing less frequently changing data used in the site header and footer. </li>
</ul>
<p>(<i>Note: If this approach interests you at all, let me know – the specifics of the interface and implementation are two much detail to include here, but I can cover them in a separate post if there is interest.)</i></p>
<p>A nice bonus from using this abstraction on the current project was that it allowed us to use the current CTP of Velocity, <a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx" target="_blank">Microsoft’s new distributed cache</a>. The abstraction – together with our use of the <a href="http://www.castleproject.org/container/index.html" target="_blank">Windsor IoC container</a> – provided us with a handy safety net: if at any point we found an issue with using Velocity, switching back to the standard HTTP cache would be a simple configuration change. As I’ll cover in a future post our soak testing showed that Velocity is fast and stable, but even post go-live, it would still be a simple matter to make the switch if necessary. One of the tenets of <a href="http://www.amazon.co.uk/Lean-Software-Development-Agile-Toolkit/dp/0321150783/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1255378929&amp;sr=8-1" target="_blank">lean development</a> is that you should delay decision making until the <a href="http://www.codinghorror.com/blog/archives/000705.html" target="_blank">last responsible moment</a> – for us, the last responsible moment for deciding on a caching solution could be deferred until go-live, by which point we’d been using Velocity for around 5 months.</p>
<h2>Applying caching in the controllers</h2>
<p>Our first area of focus was to look at caching the results of controller actions. One of the great things about ASP.NET MVC is that things are so much simpler than in the web forms world (<a href="http://blog.codeville.net/2009/10/08/aspnet-mvc-learning-resource-request-handling-pipeline-poster/" target="_blank">check this out for a pretty picture of the request handling pipeline</a>). It’s far easier to understand where you do and don’t need to apply caching in your application code, and we realised that the most effective thing to do was to put the majority of ours in the controllers.</p>
<p><a href="http://consultingblogs.emc.com/howardvanrooijen/" target="_blank">Howard</a> posted a diagram of our architecture on his <a href="http://consultingblogs.emc.com/howardvanrooijen/archive/2009/10/11/Simplify-Separation-of-Concerns-in-ASP.NET-MVC-with-AutoMapper.aspx" target="_blank">recent blog post</a> about <a href="http://www.codeplex.com/AutoMapper" target="_blank">AutoMapper</a>. From this you might be able to infer that our controllers tend to follow a pretty simple pattern:</p>
<ol>
<li>Input view model is populated from request data by a model binder. </li>
<li>Input view model is mapped to domain objects. </li>
<li>Application services layer is used to do work with those domain objects. </li>
<li>Resulting domain objects are translated back into a view model that can be passed to the view. </li>
<li>Appropriate ActionResult is returned. </li>
</ol>
<p>This is the most complex scenario – not all steps are required for every action.</p>
<p>In an ideal world we’d be caching the ActionResults returned by the controllers but this isn’t something we can do because they aren’t serializable and therefore can’t be cached in Velocity. We therefore have to settle for caching the ViewModel for each action, which gives us this pattern:</p>
<div style="padding:5px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:01a6bc52-484b-4c69-98a4-eb04ecea906c" class="wlWriterSmartContent">
<div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:&#39;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;">
<div style="background:#ddd;max-height:300px;overflow:scroll;padding:0;">
<ol style="background:#ffffff;margin:0 0 0 35px;">
<li>&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color:#0000ff;">public</span> ActionResult Index() </li>
<li style="background:#f3f3f3;">&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </li>
<li>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color:#0000ff;">return</span> View(Views.Index, MasterPages.Default, <span style="color:#0000ff;">this</span>.IndexInner()); </li>
<li style="background:#f3f3f3;">&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </li>
<li></li>
<li style="background:#f3f3f3;">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [Cached] </li>
<li>&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color:#0000ff;">private</span> MyViewModel IndexInner() </li>
<li style="background:#f3f3f3;">&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </li>
<li>&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </li>
<li style="background:#f3f3f3;"></li>
</ol></div>
</p></div>
</p></div>
<p>The [Cached] attribute is actually a <a href="http://www.postsharp.org/" target="_blank">PostSharp aspect</a> that caches the result of the method call, and I have both good intentions and half finished blog posts on this subject. </p>
<p>If the action method takes parameters, these are passed straight through to the ActionInner method – we do the minimum amount of work possible in the action method itself.</p>
<h2>Dealing with changing content in the CMS</h2>
<p>In an ideal world, we would set most of the caches to have an extremely long life, then implement a mechanism to allow individual caches to be flushed as and when required. Anyone who has ever used Microsoft Commerce Server will be familiar with the <a href="http://msdn.microsoft.com/en-us/library/microsoft.commerceserver.runtime.sitecacherefresh.aspx" target="_blank">SiteCacheRefresh</a> handler which allows caches to be cleared in response to a web request. However we encountered an issue here: the current release of Velocity (CTP3), does not support enumeration or flushing of named caches &#8211; these operations are limited to cache regions. The downside with cache regions is that they are tied to a single server, which pretty much removes the benefits of using a distributed cache.</p>
<p>As I’ve previously mentioned, our system uses N2 for Content Management and the majority of our pages are represented in the CMS. We therefore cached the ViewModel for each page using a key based on the unique ID of the page and the last updated date of the page. This works well because it means that pages can be cached indefinitely, but as soon as someone makes a change to the page then a new version will be created and cached. Obviously this means that the old version will be lingering in the background – the downside to this approach is that you may well fill up the cache more quickly and require Velocity to evict more frequently.</p>
<p>This approach isn’t perfect – it doesn’t cover the product pages, and doesn’t take care of changes in the site hierarchy that would mean we need to regenerate the navigation.&#160; As a result, we’ve implemented an additional hack: all cache keys used for content pages include the last updated time of a single page within the site. Touching that page will cause every cache key used at the controller level to change. I don’t particularly like it, but it does work.</p>
<p>The longer term plan would be to look at this again as and when Velocity moves on. With any luck, the next CTP (<a href="http://blogs.msdn.com/velocity/archive/2009/06/10/velocity-next-release-ctp4.aspx" target="_blank">now overdue</a>) will make some changes in this area. The ideal plan would be to:</p>
<ul>
<li>Hook into N2’s persistence mechanism – from reading the documentation and looking at the code, it should be possible to receive a notification when things change.&#160; This could then be used to remove stale objects from the cache, or flush an entire named area as required. </li>
<li>Implement a restricted controller that allows clearing of individual caches (in the style of the CS SiteCacheRefresh handler mentioned above.) This would be useful if we needed to clear a cache in response to an external action – such as an ETL process pulling data from a back office system. </li>
</ul>
<h2>Caching elsewhere in the application</h2>
<p>Once we’d implemented the caching in the controllers and configured the NHibernate second-level cache in both our custom code and N2, there were very few places in our model layer that we needed to apply caching. Once again we hit the point of diminishing returns – we could spend time profiling the application and identifying any remaining bottlenecks, or we could move on and look at what we expected to be the final big win: output caching, which I’ll be talking about in the next post of this series.</p>
<h2>A final word about caching</h2>
<p>On a lot of projects I’ve worked on, caching is something that tends to be implemented at the end. There are advantages to this – it can help to avoid premature optimisation, and you will (hopefully) have a good understanding of the moving parts in your codebase. However, there is one major downside that anyone who’s done this will be familiar with: once you check in the changes, every single bug that is raised for the application will be blamed on your caching. Accept it, live with it, and be prepared to be known as a) grumpy, and b) easy to wind up. Just take satisfaction in the knowledge that when you get it right, you will be setting yourself up for success when you finally put your site live.</p>
<p>As always, I’d appreciate feedback on these posts – either by leaving a comment, dropping me an email or via Twitter.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net, asp.net mvc, performance, s#arp architecture <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/23/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=23&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/10/12/optimising-an-asp-net-mvc-web-site-part-3-application-caching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>
	</item>
		<item>
		<title>Optimising an ASP.NET MVC web site, part 2: Database and NHibernate</title>
		<link>http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/</link>
		<comments>http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 23:28:00 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Technical Stuff]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[nhibernate]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[s#arp architecture]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://jonathangeorge.wordpress.com/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/</guid>
		<description><![CDATA[Note: This was originally posted on my old blog at the EMC Consulting Blogs site. This is part 2 in a series of posts on optimisation work we carried out on my current project – an ASP.NET MVC web site built using S#arp Architecture, NHibernate, the Spark view engine and Solr. Please see “Optimising an [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=22&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>Note: This was originally posted on </strong><a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"><strong>my old blog</strong></a><strong> at the </strong><a href="http://consultingblogs.emc.com/"><strong>EMC Consulting Blogs site</strong></a><strong>.</strong></p>
<p><i>This is part 2 in a series of posts on optimisation work we carried out on my current project – an ASP.NET MVC web site built using <a href="http://code.google.com/p/sharp-architecture/" target="_blank">S#arp Architecture</a>, <a href="https://www.hibernate.org/343.html" target="_blank">NHibernate</a>, the <a href="http://sparkviewengine.com/" target="_blank">Spark view engine</a> and <a href="http://lucene.apache.org/solr/" target="_blank">Solr</a>. Please see <a href="http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-1-introduction/">“Optimising an ASP.NET MVC web site part 1 – Introduction”</a> for the background.</i></p>
<p>Whilst there are many different things you can do to a web application to kill performance, having a badly implemented database &#8211; or a well implemented database that you access in a bad way – has got to be right up there with the best. We therefore made the database our first port of call, and started off with a pretty simple approach – fire up&#160; SQL Server Profiler, start a new trace and see what the pain points are in each database. </p>
<h2>Using SQL Server Profiler to find data access mistakes</h2>
<p>As I mentioned in the introduction, the goal of our optimisation wasn’t to do everything, just to get the main things we thought were causing problems before we began our load testing. If you use the TSQL_Duration template in SQL Profiler for your trace, you can hit your site and quickly see what the most expensive queries are. </p>
<p><a href="http://jonathangeorge.files.wordpress.com/2009/11/sampletsql_durationtrace.png"><img style="display:inline;border-width:0;" title="Sample TSQL_Duration Trace" border="0" alt="Sample TSQL_Duration Trace" src="http://jonathangeorge.files.wordpress.com/2009/11/sampletsql_durationtrace_thumb.png?w=680&#038;h=345" width="680" height="345" /></a> </p>
<p>The screenshot above shows the results of repeatedly executing three different stored procedures in a random order. As you can see, the results are organised in ascending order of cost, with the interesting column being “Duration” – which shows the execution time in milliseonds.</p>
<p>When <a href="http://blogs.conchango.com/howardvanrooijen/default.aspx" target="_blank">Howard</a> first ran this against some of our landing and search result pages he quickly noticed a large nugget of smelliness at the bottom of the list, in the form of repeated calls to a stored procedure that was taking a whopping 400ms to execute. Whilst 400ms is not a long time – I’m sure it’s taken longer than that for you to read this sentence so far – when you call it 20 times you’ve suddenly spent 8 seconds just on database calls before any other page activity.</p>
<p>Digging into this identified three separate, but related issues.</p>
<p><b>1. One of our NHibernate mappings included a view based on a recursive query</b></p>
<p>Of course, this was something we’d told NHibernate to do. Our entities are organised hierarchically, and an entity can appear in multiple positions in the hierarchy. When we pass entity data to Solr for indexing, we work out the full list of paths for an entity and pass that through (see item 3 for more details.) This was done by creating a CTE to generate the list of hierarchy paths for each entity. </p>
<p>For the uninitiated, a <a href="http://msdn.microsoft.com/en-us/library/ms190766.aspx" target="_blank">Common Table Expression</a> (or CTE) is a T-SQL construct that (amongst other things) <a href="http://msdn.microsoft.com/en-us/library/ms186243.aspx" target="_blank">enables you to execute recursive queries</a>. They are very handy when dealing with hierarchical datasets, but aren’t the most efficient queries you can execute. Some time after the initial creation of the view, we’d realised that it would be useful to have the data it contained as part of our entity so we added a mapping into our NHibernate configuration. This meant that accessing that data would cause NHibernate to go off and execute a SELECT statement which included a join from the main entity table to the view. This query took in the region of 400ms. </p>
<p>We have two main types of page on the site landing pages and search/browse pages. The landing pages were causing this query to be executed 13 times and the browse pages were causing it to be executed 20 times, so it’s no wonder that performance had dropped. Whilst the view was never intended for use in this way, the requirement to have the data as part of our entity was still valid. </p>
<p>The simple solution to the problem was essentially to materialize the view. SQL Server can do this by <a href="http://msdn.microsoft.com/en-us/library/dd171921.aspx" target="_blank">turning the view into an indexed view</a> – adding a unique clustered index to it does this. However, this approach isn’t applicable when the SELECT statement for the view uses a CTE, so we went with a more basic approach – since our product catalogue is actually managed in the back office and populated via ETL, we replaced the view with a table (complete with all the appropriate indexes) and tweaked the ETL to populate this table at the same time as all the rest.</p>
<p>For the pages in question, load time dropped from around 8 seconds to under 2, at which point we all got quite excited. However, this wasn’t solely to do with the materialisation of the view, as the investigation also showed up that…</p>
<p><b>2. Everything was being lazy loaded </b></p>
<p>By default, NHibernate uses lazy loading across the board. Depending on your object model and how it is used, this can lead to massive inefficiences. The classic example is the &quot;SELECT N+1” anti-pattern, in which you retrieve an entity from a repository then iterate over a collection on that entity. If you’ve left NHibernate lazy loading the values, then this results in a SELECT statement being issued for every iteration of the loop. Have a look at <a href="http://nhprof.com/Learn/Alert?name=SelectNPlusOne" target="_blank">this page on the NHibernate Profiler site</a> for more information.</p>
<p><a href="http://blogs.conchango.com/howardvanrooijen/default.aspx" target="_blank">Howard</a> spent some time using the <a href="http://nhprof.com/" target="_blank">NHibernate profiler</a> to better understand what our app was doing, and made a number of tweaks to our mapping configuration to apply eager loading where it made sense. This provided another significant improvement, dramatically reducing the number of database calls made by the application.</p>
<p><b>3. An architectural rule imposed for performance reasons had been broken</b></p>
<p>We’d made an architectural decision to drive the search and browse functions on our website exclusively from Solr. We did this because it gives us more options for scalability. Since all the data in question comes from a single database, pulling the data directly out of that database would mean that as website load increases then so does the load on the database. The problem with that is that it’s difficult to scale a single database out &#8211; you can throw CPUs and RAM at your database server, but you’re always going to hit a limit, at which point you face some architectural challenges. This kind of basic architecture is shown in the following diagram:</p>
<p><a href="http://jonathangeorge.files.wordpress.com/2009/11/simplearchitecture.png"><img style="display:inline;border-width:0;" title="Simple architecture" border="0" alt="Simple architecture" src="http://jonathangeorge.files.wordpress.com/2009/11/simplearchitecture_thumb.png?w=432&#038;h=432" width="432" height="432" /></a> </p>
<p>Even though the main entity database is static, meaning that it would be possible to have a number of replicas of this database (potentially even one per webhead), this would require architectural change and would bring with it a new set of issues around data consistency. By pushing that load onto Solr, which has a far more straightforward scale-out story, we can grow far further without requiring a redesign. Solr basically stores a flat set of data in a form optimised for searching, and provides access via a web service. This means it is straightforward to have multiple instances of Solr running behind a load balancer. Solr makes this kind of setup even easier, as it supports a master-slave configuration as shown in the following diagram (I apologise now for the proliferation of connecting lines – I’m more of a <a href="http://simonmunro.com/2009/09/08/it-architecture-the-usual-suspects/" target="_blank">reluctant architect than a Powerpoint architect</a>):</p>
<p><a href="http://jonathangeorge.files.wordpress.com/2009/11/withsolrtier.png"><img style="display:inline;border-width:0;" title="With solr tier" border="0" alt="With solr tier" src="http://jonathangeorge.files.wordpress.com/2009/11/withsolrtier_thumb.png?w=431&#038;h=486" width="431" height="486" /></a> </p>
<p>In this example, the web tier will still talk direct to the data tier for some tasks – it’s unavoidable. However, we introduce the search tier which consists of a set of load balanced search servers, each of which contains an identical copy of the search index. In order to build that index, we push data from the database into the Solr master server, and the Solr master server indexes it and pushes the result out to each slave. If you can see past the nasty mess of lines, it should be obvious that as load grows, adding more webheads and/or Solr slaves is a relatively trivial operation. </p>
<p>However, you can have the best intentions in the world when you design your solution, but if you then go on to break the rules then it’s not going to happen. In our case, the code had ended up in a state where for each result retrieved from a Solr search, a database query would be made. Not only that, but the query in question was the horribly expensive one I mentioned in point 1.</p>
<p>This will no doubt cause some brow-wrinkling activity if you’re paying attention, as I mentioned that the original intended purpose of the view being used for the expensive query was to push data into Solr – so why, if the data was already in there, would we be accessing it again from the database once we’d pulled it out of Solr?</p>
<p>I can think of a number of good explanations, the best of which might be “My name’s Jon, and <a href="http://subwindow.com/articles/2" target="_blank">I’m a terrible programmer</a>”. The day I get it right 100% of the time is quite probably the day I get to decide which of my Ferrari’s I drive to work, as well as the day that my projects no longer require testers, and I doubt that will ever happen. Maybe I just missed the <a href="http://xkcd.com/323/" target="_blank">Ballmer Peak</a> on that day, but whatever happened, I’m just happy when the mistakes I make are as easy to identify and fix as this one was.</p>
<h2>Using the SQL Server Database Engine Tuning Advisor</h2>
<p>In tandem with this, we also made use of the SQL Server Database Engine Tuning Advisor. This is the next stage of evolution for the Index Tuning Wizard that (I believe) first appeared in SQL Server 2000. The <a href="http://msdn.microsoft.com/en-us/library/ms173494.aspx" target="_blank">MSDN page for it is here</a>; the short (aka .NET developer) version is that you put a trace file into one end, and out of the other comes a variety of changes you can make to your database to make it go faster.</p>
<p>In order to generate the input, you use SQL Server Profiler with the “Tuning” template. Once this is running, and saving the trace to a file, you need to generate a “typical” load against your application. There are various ways to do this, ranging from fully manual to fully automated. We were fortunate on our project that we had a complete set of <a href="http://seleniumhq.org/" target="_blank">Selenium</a> tests for the site and a way of running them as part of the build. I’m hoping that Tom, the consultant responsible for this, will start blogging about it at some point as it’s really interesting stuff. It meant that to generate our trace, all we had to do was start the profiler, kick of the test suite and go for a beer. The next morning, we pushed the resultant file through the tuning advisor and received our recommendations out of the other end. There was little we disagreed with, and most of the recommendations were subsequently applied to the database. </p>
<h2>The rest?</h2>
<p>You may have noticed that the main focus in this post has been around the way the application accessed the data, rather than the way the database was built. Over the duration of the project, and in addition to the fantastic data architect we had in the team, we’ve had guest appearances by <a href="http://consultingblogs.emc.com/jamesrowlandjones/" target="_blank">JRJ</a>, <a href="http://sqlblog.com/blogs/jamie_thomson/" target="_blank">Jamie</a> and <a href="http://consultingblogs.emc.com/simonmunro/" target="_blank">Simon</a>, so it shouldn’t come as a massive surprise that the database works well. EMC Consulting is rightly proud of the database guys we have on the team and whilst I’m sure that there are many further tweaks that could be made to our databases to add further go-faster stripes, they aren’t needed at the moment.&#160; Optimisation is one of many things that doesn’t benefit by having the word “premature” put in front of it – it’s basically another form of&#160; <a href="http://en.wikipedia.org/wiki/You_ain't_gonna_need_it" target="_blank">YAGNI</a>. So, until testing proved otherwise, we were happy to stop at this point and move on to something else.</p>
<p><i>In the next exciting epsiode of “Optimising an ASP.NET MVC web site”, we look at a pattern for applying application layer caching. Don’t touch that dial!</i></p>
<p>Please let me know what you think of my blog posts, either by commenting, dropping me an email, or via Twitter.</p>
<p><a href="http://twitter.com/jon_george1" target="_blank">@jon_george1</a></p>
<br /> Tagged: asp.net, asp.net mvc, nhibernate, performance, s#arp architecture, solr <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathangeorge.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathangeorge.wordpress.com/22/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathangeorge.co.uk&#038;blog=10577589&#038;post=22&#038;subd=jonathangeorge&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathangeorge.co.uk/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6038fabf4927137a504608f99b48f91f?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jonathan</media:title>
		</media:content>

		<media:content url="http://jonathangeorge.files.wordpress.com/2009/11/sampletsql_durationtrace_thumb.png" medium="image">
			<media:title type="html">Sample TSQL_Duration Trace</media:title>
		</media:content>

		<media:content url="http://jonathangeorge.files.wordpress.com/2009/11/simplearchitecture_thumb.png" medium="image">
			<media:title type="html">Simple architecture</media:title>
		</media:content>

		<media:content url="http://jonathangeorge.files.wordpress.com/2009/11/withsolrtier_thumb.png" medium="image">
			<media:title type="html">With solr tier</media:title>
		</media:content>
	</item>
	</channel>
</rss>
