<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>General</title>
        <link>http://www.codeofrob.com/category/7.aspx</link>
        <description>Anything that doensn't fit into a specific category</description>
        <language>en-GB</language>
        <copyright>Rob Ashton</copyright>
        <generator>Subtext Version 2.1.2.2</generator>
        <item>
            <title>Multi-tenancy in ASP.NET MVC - Controller Actions (Part I)</title>
            <link>http://blog.codeofrob.com/archive/2010/02/14/multi-tenancy-in-asp.net-mvc-controller-actions-part-i.aspx</link>
            <description>&lt;p&gt;&lt;strong&gt;Previous entries in the series&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://codeofrob.com/archive/2010/02/01/multi-tenancy-in-asp.net-mvc-why-do-we-want-to.aspx"&gt;Why we want it&lt;/a&gt; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://codeofrob.com/archive/2010/02/04/multi-tenancy-in-asp.net-mvc-breaking-it-down.aspx"&gt;Breaking it down + Themes&lt;/a&gt; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://codeofrob.com/archive/2010/02/08/multi-tenancy-in-asp.net-mvc-views.aspx"&gt;Views&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;font face="Arial"&gt;In the last entry, we covered how and why we might want to replace existing views and partial views from the core application with our own from modules. We also covered that with this ability it was possible to add entirely new views and partial views.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;However, views need actions and actions come from controllers. If we add a new view to the application and the core application does not support that path with an action, that view cannot be loaded.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;It stands to reason therefore that our modules need the ability to add new controller actions (and indeed replace existing actions) at run-time on a per-request basis - again assuming we're going for full on multi-tenancy.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Actions come from controllers, and by default controllers come from the main web assembly. Now obviously our modules should be as self contained as possible and therefore probably each have their own assemblies so they can be developed separately and added to the project ad-hoc.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Once again, the ASP.NET MVC team have given us an extensibility point with which to override this default behaviour with the ability to implement our own controller factories.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Resolving actions&lt;/strong&gt;&lt;br /&gt;
As with the last topic, I will assume the presence of a configuration provider that can tell us which modules are loaded.&lt;br /&gt;
For purposes of simplicity, the Module class now contains a reference to an Assembly that we'll assume was loaded in when the configuration was last scanned.&lt;br /&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;pre class="brush: csharp;" title="code"&gt;    public class Module
    {
        public string Id
        {
            get;
            set;
        }

        public Assembly Assembly
        {
            get;
            set;
        }
    }
&lt;/pre&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The job of the ControllerFactory is another well documented concept; when a controller is required, the factory is invoked with the name of the controller being requested and the current request data. It is expected to return an instance of the controller (which is used for that single request), and then just like the ViewEngine is given that controller to dispose of at the end of the request.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The simplest solution is clearly going to be that we look at the context we have access to and then work out which controller to return based on that context.&lt;br /&gt;
The context in this case being the name of the controller, the action being requested and the collection of modules which are currently active for this request.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Each module can therefore hold their own controllers with their own actions, and the controller factory can select which controller to return when a specific action is being invoked.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I implement my controller factory from the base interface, which is System.Web.Mvc.IControllerFactory:&lt;/font&gt; &lt;/p&gt;
&lt;pre class="brush: csharp;" title="code"&gt;    public class ModuleControllerFactory : IControllerFactory
    {
        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            throw new NotImplementedException();
        }

        public void ReleaseController(IController controller)
        {
            throw new NotImplementedException();
        }
    }
&lt;/pre&gt;
&lt;p&gt;ReleaseController can just check for IDisposable and dispose if necessary, so we'll take that as read and focus on what we need to do in order to create the controller.&lt;/p&gt;
&lt;/font&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;
&lt;h3&gt;&lt;font face="Arial"&gt;&lt;strong&gt;The Goal&lt;/strong&gt;&lt;/font&gt;&lt;/h3&gt;
&lt;/strong&gt;&lt;/font&gt;
&lt;p&gt;&lt;font face="Arial"&gt;These are the modules exposed by the application, the controllers they provide and the actions those controllers have on them.&lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;CoreModule&lt;/font&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;font face="Arial"&gt;HomeController&lt;/font&gt; &lt;/li&gt;
        &lt;li&gt;&lt;font face="Arial"&gt;ActionResult Index();&lt;/font&gt; &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;ModuleOne&lt;/font&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;font face="Arial"&gt;HomeController&lt;/font&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;font face="Arial"&gt;ActionResult Extra();&lt;/font&gt; &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;ModuleTwo&lt;/font&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;font face="Arial"&gt;HomeController&lt;/font&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;font face="Arial"&gt;ActionResult Index();&lt;/font&gt; &lt;/li&gt;
            &lt;li&gt;&lt;font face="Arial"&gt;ActionResult Extra();&lt;/font&gt; &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;font face="Arial"&gt;OtherController&lt;/font&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;font face="Arial"&gt;ActionResult Index(); &lt;/font&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; WIth the set-up, the following behaviour is desired:&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Core Module loaded:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;/Home/Index requested =&amp;gt; CoreModule Index Invoked&lt;br /&gt;
/Home/Extra requested =&amp;gt;  Action Not found&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Core + ModuleOne Loaded&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;/Home/Index requested =&amp;gt; CoreModule Index Invoked&lt;br /&gt;
/Home/Extra requested =&amp;gt;  ModuleOne Extra Invoked&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Core + ModuleOne + ModuleTwo Loaded (in that order)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;/Home/Index requested =&amp;gt; ModuleTwo Index Invoked&lt;br /&gt;
/Home/Extra requested =&amp;gt; ModuleTwo Extra Invoked&lt;br /&gt;
/Other/Index requested =&amp;gt; ModuleTwo Index Invoked&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;h3&gt;&lt;font face="Arial"&gt;A Solution&lt;/font&gt;&lt;/h3&gt;
&lt;p&gt;This is actually quite tricky, as the solution is going to involve not only scanning for the controllers, but scanning for methods on those controllers that match the actions being requested.&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;There are a lot of rules involved already in MVC selecting the right method to call from a controller, and we don't want to go down the route of duplicating this, so this is where we set a convention and say that if *any* action is found with the name being requested, that we'll use that controller and assume that all the necessary permutations of that action will be provided too. (A post action vs Get action for example).&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;There are two parts to solving this problem, finding the type we want to create, and creating the controller from that type.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The process will be similar to that of the ViewEngine example:&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;1) Reverse the module list order so we have the most recently loaded first&lt;br /&gt;
2) Scan all the types in the assembly for that module&lt;br /&gt;
3) Find a type with the name we're looking for ( &amp;lt;Name&amp;gt;Controller )&lt;br /&gt;
4) Scan the methods on that type to find the action we're looking for&lt;br /&gt;
5) If found, return this type&lt;br /&gt;
6) Else Continue&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Obviously reflecting on all these types is a slow process, and we should cache the type once found by configuration id, controller name and action name. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Here is some code which loosely achieves the above:&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;pre class="brush: csharp;" title="code"&gt;private Type FindControllerType(String controllerName, RequestContext requestContext, Configuration currentConfiguration)
        {
            // Generate the type name we're looking for
            String controllerTypeName = string.Format("{0}Controller", controllerName);

            // Get the action and therefore method name we're looking for
            String actionName = (string)requestContext.RouteData.Values["action"];

            // TODO: Check Cache here

            // Get modules in reverse order
            var searchModules = currentConfiguration
                .Modules
                .Reverse();

            foreach (var module in searchModules)
            {
                // Get all the types in the assembly
                Type[] controllerTypes = module.Assembly.GetTypes()
                    .Where(
                        t =&amp;gt;
                            // Where the type name is the one we're looking for
                            t.Name == controllerTypeName &amp;amp;&amp;amp;

                            // Where it can be cast to a controller
                            typeof(IController).IsAssignableFrom(t) &amp;amp;&amp;amp;

                            // And there is a public instance method with the name we're looking for on that type
                            t.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                            .Where(m =&amp;gt; m.Name == actionName).Count() &amp;gt; 0

                        ).ToArray();

                // Skip to the next module if no types found
                if (controllerTypes.Length == 0) { continue; }

                // Else, simply return the first one found
                return controllerTypes[0];
            }

            // Fail
            return null;
        }
&lt;/pre&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;br /&gt;
A very rudimentary controller factory implementation would therefore look something like this:&lt;br /&gt;
&lt;/p&gt;
&lt;pre class="brush: csharp;" title="code"&gt; public class ModuleControllerFactory : IControllerFactory
    {
        private IConfigurationProvider mConfigurationProvider;

        public ModuleControllerFactory(IConfigurationProvider configurationProvider)
        {
            mConfigurationProvider = configurationProvider;
        }

        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            Type t = FindControllerType(controllerName, requestContext, mConfigurationProvider.GetActiveConfiguration());
            return (IController)Activator.CreateInstance(t);
        }

        public void ReleaseController(IController controller)
        {
            IDisposable disposable = controller as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
// Etc
&lt;/pre&gt;
&lt;p&gt;&lt;font face="Arial"&gt;It is of course probably desirable to instantiate the controller using your favourite IOC container  - so for StructureMap for example instead of using Activator.CreateInstance you would call ObjectFactory.GetInstance(t);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;(Actually, you'd probably inject the container as well rather than calling ObjectFactory directly but you get the gist).&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;
&lt;h3&gt;&lt;font face="Arial"&gt;Summary&lt;/font&gt;&lt;/h3&gt;
&lt;p&gt;Essentially, we can completely re-wire this part of the ASP.NET MVC framework to do what we want it to do. We can load our controllers from wherever based on whatever context we like - and this gives us a powerful mechanism for pluggability and therefore multi-tenancy.&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I did contemplate trying to achieve this through routing - custom routing constraints and handlers - but it's not a tidy solution, it generally means having different names for your controllers, or playing havok with namespaces and configuration and because a lot of that configuration is static it often involves re-compilation.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Re-compilation is something to be avoided, as we ideally want to be able to add new customers by just modifying configuration.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Anyway, there are a number of options and this is just one of them,  I'll be hoping to cover a crazy solution using Reflection.Emit and hopefully delve into MEF before I'm done with this particular part of the multi-tenancy story.&lt;/font&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blog.codeofrob.com/aggbug/15.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2010/02/14/multi-tenancy-in-asp.net-mvc-controller-actions-part-i.aspx</guid>
            <pubDate>Sun, 14 Feb 2010 17:17:29 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/15.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2010/02/14/multi-tenancy-in-asp.net-mvc-controller-actions-part-i.aspx#feedback</comments>
            <slash:comments>12</slash:comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/15.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/15.aspx</trackback:ping>
        </item>
        <item>
            <title>DDD8 Feedback... feedback</title>
            <link>http://blog.codeofrob.com/archive/2010/02/09/ddd8-feedback.-feedback.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;The feedback from DDD8 has come in, in anonymous form and for the most part I'm completely overwhelmed by the positive response the talk garnered from the people who attended the talk.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;However, I get the feeling my talk managed to polarise the room somewhat and I'd like to respond to those that went completely the opposite way with their responses and apologise if I went a different direction to what they expected!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Varied Demos&lt;/strong&gt;&lt;br /&gt;
Okay, no defence here at all - showing you all the same website over and over again until I got around to showing the final product of the concepts( NerdDinner) was a bit unfair - I'll try to put together the demos a bit earlier than 3am the night before next time :)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I think perhaps concentrating on NerdDinner from the start and showing how I built that up might have helped, but when I put the demos together I was struggling to simplify that enough for the demos to make sense in their own right (hence the hurried individual ones)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Not enough Detail&lt;/strong&gt;&lt;br /&gt;
I never intended on going into detail on the concepts outlined - I don't feel you ever can go into detail in a talk that lasts less than an hour - nevertheless, if you'd like more detail you're all more than welcome to respond to my series on multi-tenancy with questions and more feedback! &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I already have a longer slot booked at one user group - and would be happy to spend more time on the subject at any other user groups or developer meet-ups - just ask.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Too technical&lt;/strong&gt;&lt;br /&gt;
I should have made clear in my summary that a prior knowledge of ASP.NET MVC would be useful - and I apologise for this - a few people complained about this and I'll know next time to be more up front about what I intend on covering in a session.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Too fast&lt;/strong&gt;&lt;br /&gt;
This is probably one of the most subjective responses I had, and a lot of people said they loved the pace - which kept them awake and interested throughout the talk. I don't think I'll change this in my future talks (although I might try to talk slower), but another disclaimer may well not go amiss "This talk will be fast-paced and try to throw as much information at you in an hour as your brain can cope with" &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Wrong approach&lt;/strong&gt;&lt;br /&gt;
Okay, only one person mentioned this - and said I should be using IOC to solve the issues I outlined. I'm not entirely sure (apart from the controllers) where this would have helped - so feel free to contribute to the multi-tenancy conversation in the comments of  this blog when I get to that point whoever you are!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I was also criticised by the same person for even wanting to host the same application under the same IIS instance - I believe I covered this as an option in one of my slides however and I was certainly not suggesting that I recommended keeping your customers in one basket.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I think there are masses of conversations and discussions to be had over the approach I took to solving the problem - which is why I'm now doing this blog series - to get the discussion going and come to an agreed solution between us all.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Poor distribution of Swag&lt;/strong&gt;&lt;br /&gt;
Yes yes yes, I'm sorry - I'm really bad at this kind of thing because it's not something I'm interested in - I'll try to do better next time.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Too nervous&lt;/strong&gt;&lt;br /&gt;
Guilty as charged, my first time speaking in a while - I'll try to be more confident next time&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Too confident/arrogant&lt;/strong&gt;&lt;br /&gt;
Towards the end perhaps you're right, I'm trying to work out whether this is better or worse than the above!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Ending on a high note&lt;/strong&gt;&lt;br /&gt;
In response to all the people who said my talk had great pace, great content, that it was incredibly useful and relevant, that the subject area had justice given to it, and that I clearly knew what I was talking about - thanks a bunch, rest assured that the above comments have balanced out the ego and I can still fit through doors.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Thanks to everybody who attended and asked questions - I'll be seeing you all again shortly no doubt.&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blog.codeofrob.com/aggbug/14.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2010/02/09/ddd8-feedback.-feedback.aspx</guid>
            <pubDate>Tue, 09 Feb 2010 17:28:36 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/14.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2010/02/09/ddd8-feedback.-feedback.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/14.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/14.aspx</trackback:ping>
        </item>
        <item>
            <title>Multi-tenancy in ASP.NET MVC - Why do we want it?</title>
            <link>http://blog.codeofrob.com/archive/2010/02/01/multi-tenancy-in-asp.net-mvc-why-do-we-want-to.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;I'll be gratuitously "borrowing" a lot  of material from my DDD8 slides in this post, it seemed like the right thing to do given that this series is a write-up and then continuation of that talk.&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When dealing with more than one customer in the desktop market, it is customary to have a single product which is extendable through the use of plug-ins and an API, and often you can leave it up to your consumer base to write those plug-ins and add to your product in a manner they see fit.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;In the web world it's a bit different, and you don't typically get that kind of behaviour (Facebook applications may or may not count, depending on how you look at it).&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;br /&gt;
In a simple world, you'll have a single product which is used directly off the shelf by multiple customers:&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Single product" src="http://fear.the.codeofrob.com/mt_why/single_product.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When building web applications for a varied and paying customer base, It is likely that you have customers that are fickle and will want things done their way. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;It often does not make business sense to turn good business down, and the business is what pays the hungry developer and thus when you finally get a customer who wants things done differently,  the business tells the developer to jump and the business's required response is the proverbial "how high?".&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Consider the above diagram then, and imagine Customer A asking for something 'just a little bit different' and think about what your options could be.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;We'll get the obvious dusted out of the way first:&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="if( featureIsEnabled....)" src="http://fear.the.codeofrob.com/mt_why/feature_code.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When I switched to the above code as a slide in my multi-tenant talk, I was greeted with laughter, but we've all known products which have ended up with such delightful nuggets in them. &lt;br /&gt;
It's blindingly obvious that it's not the right solution, and that as you progress down the route of making further modifications for either Customer A, B or C you'll end up with an un-maintainable mess of switches and flags. 'Nuff said.&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;You could then decide that you're going to keep that customer as a new product in its own right - that would remove the need for all those on-off switches.&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;img alt="A bespoke copy" src="http://fear.the.codeofrob.com/mt_why/bespoke_copy.png" /&gt;&lt;br /&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;This should very obviously be a big no-no as maintaining that then bespoke product and keeping it up to date with any changes then made to your core product is going to be nothing more than a giant headache. &lt;br /&gt;
As you get more customers, the number of developers you'll need to hire will increase almost in direct proportion to the number of codebases you have to maintain!  (Again, I've seen this done - so don't think I'm just pointing out the obvious for the sake of it)&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Let's move onto the more-often used approach, of branching from a base product for your different needs, and utilising the power of a source control system to keep changes in sync between your code-bases.&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;img alt="Branching as an alternative" src="http://fear.the.codeofrob.com/mt_why/bespoke_branch.png" /&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Customer A can be kept up to date by merging changes from the core product, and Customer B/C can get additional features from Customer A's branch if and when they desire it.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;At first glances, it seems like this solution fits our needs - and indeed it can work well in a lot of given  scenarios. The problem comes when you scale this solution up to more than this small example - as few of us are (un)lucky enough to be able to deal with only three customers and remain financially viable!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Here is a small example of 30 customers sharing 15 code-bases!&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;img alt="A mess of branching dependencies" src="http://fear.the.codeofrob.com/mt_why/bespoke_mess.png" /&gt;&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Yowsers! &lt;br /&gt;
How do you keep track of who has what features? &lt;br /&gt;
How do you test all of those different branches of code? &lt;br /&gt;
How do you deploy those branches of code?&lt;br /&gt;
How do you make a new version of the product and serve it to a customer?&lt;br /&gt;
How many developers do you need to manage that process?&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;It's never as simple as it looks, and you end up with not only the above problems, but you end up with the additional problems of what happens when a branch becomes radically different and you're unable to merge changes around.&lt;br /&gt;
&lt;/font&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;There is too much developer interaction here - and your skilled staff end up having to spend most of their time creating new branches/pushing changes around instead of spending their time doing what they're actually trained to do - writing code. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;br /&gt;
Adding a new customer shouldn't be about changing code, it should be about manipulating configuration, and modifying a customer shouldn't be about changing code, it should also be about manipulating configuration. &lt;br /&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;In other words, problems should only be solved once - and configuration should be used to give or take features to and from customers.&lt;br /&gt;
&lt;/font&gt;&lt;font face="Arial"&gt;&lt;font face="Arial" /&gt;&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;
&lt;h3&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;&lt;strong&gt;Enter multi-tenancy...&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/h3&gt;
&lt;/strong&gt;&lt;/font&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The core concept of a well written multi-tenant application is that you should have a single code base, and a number of configurations - where each configuration tells the runtime what functionality should be available and what the look/feel should be.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Before continuing, I'd like to define a few of the terms I'll be using throughout this series of blog entries.&lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;Module: A discrete set of functionality&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;Theme: The look and feel&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;Configuration:  A selection of modules, and a single theme&lt;/font&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;font face="Arial"&gt;This is a personal leaning, and I know that some people would set this up differently. Each to their own, we've got to draw lines somewhere!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;Anyway - as far as I'm concerned, Multi-tenancy gives us some of the following benefits:&lt;/font&gt; &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Deployment becomes a simple case of installing your application onto a server, and setting up the configurations for that application.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When a request comes in, context is determined by some means (auth credentials, the hostname, whatever), and the relevant configuration is selected from that context. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;img alt="A single server serving multiple customers" src="http://fear.the.codeofrob.com/mt_why/multi_tenant_single.png" /&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;font face="Arial"&gt;This is a very simple way of working, and if you design your application correctly, it becomes obvious that your hosting/maintenance costs can be reduced.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;You can have multiple servers with the exact same codebase installed on them, and with all the configurations available to them (In other words, identical).  Scaling up becomes a simple matter of adding more of those identical servers - and if you're really smart you can load balance across your VPSs and power them up/down as required. &lt;br /&gt;
You no longer need to worry (too much) about the fact that you have all of those customers, and you can concentrate on the health of your system as a whole.&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Load balanced multi-tenant system" src="http://fear.the.codeofrob.com/mt_why/multi_tenant_balanced.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
 Some more benefits:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;You add a feature once, and deploy it to your customers through the use of configuration&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;You can fix a bug, and deploy the fix once &lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt; Potentially easy management of your infrastructure (This actually comes through good design, and multi-tenancy just aids in that goal)&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;Developers get to spend their time coding new features/fixing bugs&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;New customers can have a site created in minutes and start to give feedback immediately&lt;/font&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Everybody is a winner and we all get to go home and have pie and punch.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;In the next entry, things will hot up as I'll start to look at ASP.NET MVC and determine the components that we can use to aid us in creating a multi-tenant application.&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blog.codeofrob.com/aggbug/10.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2010/02/01/multi-tenancy-in-asp.net-mvc-why-do-we-want-to.aspx</guid>
            <pubDate>Mon, 01 Feb 2010 22:10:22 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/10.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2010/02/01/multi-tenancy-in-asp.net-mvc-why-do-we-want-to.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/10.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/10.aspx</trackback:ping>
        </item>
        <item>
            <title>Multi-tenancy and ASP.NET MVC</title>
            <link>http://blog.codeofrob.com/archive/2010/01/31/multi-tenancy-and-asp.net-mvc.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;I spoke about this chestnut briefly at DDD8, and I want to start expanding on the subject.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;My plan is over the next few weeks to start talking more about multi-tenancy in our web-apps, and to get everybody else doing the same - speaking to other developers after my talk I realised that we're not alone, people are working on solutions but they're just not talking about it.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;By getting some dialogue going, I hope we can generate a public description of what is good and what is bad about attempting to build multi-tenant applications on top of ASP.NET MVC, and what our possible avenues of achieving this can be.&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The suggested topics I aim to cover in this series of blog entries will (to begin with) be somewhere along these lines: (As I've already written most of the material!)&lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;What is multi-tenancy and why do we want it?&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;The building blocks of a multi-tenant application in ASP.NET MVC&lt;/font&gt;&lt;/li&gt;
    &lt;font face="Arial"&gt;
    &lt;li&gt;How I integrated MvcEx into NerdDinner to give it some multi-tenant capabilities&lt;/li&gt;
    &lt;/font&gt;&lt;/ul&gt;
    &lt;p&gt;If there is anything else you think I should cover as part of this series, then let me know by either Twitter or the comments field below.&lt;/p&gt;
    &lt;p&gt;&lt;font face="Arial"&gt;I am loathe to go into detail on what I consider to be the other 90% of the multi-tenancy story - your domain, the rest of your codebase, managing your databases/configurations etc, as you can get all of that information from people who are far more versed in the subject than I.&lt;/font&gt;&lt;/p&gt;
    &lt;p&gt;&lt;font face="Arial"&gt;But, if pushed on a particular subject I guess I will describe how I deal with those issues in the codebases I have control over, and you'll have to take it (as you should take anything written on these pages) with a pinch of salt.&lt;br /&gt;
    &lt;/font&gt;&lt;/p&gt;
    &lt;/font&gt;&lt;img src="http://blog.codeofrob.com/aggbug/9.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2010/01/31/multi-tenancy-and-asp.net-mvc.aspx</guid>
            <pubDate>Sun, 31 Jan 2010 20:16:24 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/9.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2010/01/31/multi-tenancy-and-asp.net-mvc.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/9.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/9.aspx</trackback:ping>
        </item>
        <item>
            <title>DDD8 - Post Event</title>
            <link>http://blog.codeofrob.com/archive/2010/01/31/ddd8-post-event.aspx</link>
            <description>&lt;p&gt;Wow.&lt;/p&gt;
&lt;p&gt;That was a wonderful day, and the sessions I ended up going to were:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;@ICooper's session on MVC Architecture (preaching the choir but good to be re-assured) &lt;/li&gt;
    &lt;li&gt;@robashton's session on Multi-tenant ASP.NET MVC (obviously) &lt;/li&gt;
    &lt;li&gt;@holytshirt's session on Mono (Good to see this project is advancing well) &lt;/li&gt;
    &lt;li&gt;@garyshort's session on JClosure (Lovely!) &lt;/li&gt;
    &lt;li&gt;@blowdart's session on the crystal maze &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last session was interrupted constantly by the MVPs and associated crowd because Barry is leaving the UK and heading off to MS to learn how to spell :)&lt;/p&gt;
&lt;p&gt;There isn't much specifically to talk about really, it's been said by everybody. The event was well organised, the post-event meal was also surprisingly kept in control and the post-event drinks ... well I'd had no sleep the previous night so I left early. I believe fun was had by all however.&lt;/p&gt;
&lt;p&gt;My talk? I think it went okay - I was a bit nervous presenting on a subject that doesn't get talked about openly all that much, and worried the audience might throw a few massive spanners in the works (although I am open to change, I don't want to be told outright I'm wrong in the middle of a talk!)&lt;/p&gt;
&lt;p&gt;I spoke a bit fast, and had a minor emergency at the start when realising I needed an adapter for my laptop, but was saved by the team whose job it was to babysit me and massive thanks goes to them for saving my presentation :)&lt;/p&gt;
&lt;p&gt;My slides can be found &lt;a href="http://fear.the.codeofrob.com/ddd8slides.zip"&gt;here&lt;/a&gt;, and demo code can be found &lt;a href="http://fear.the.codeofrob.com/ddd8code.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The nerd dinner multi-tenant example can be found on the MvcEx codeplex site (&lt;a href="http://mvcex.codeplex.com"&gt;http://mvcex.codeplex.com&lt;/a&gt;) - but I'll be hoping to improve it beyond its "suitable for demo" stage and do some blog entries on the rationale behind some of the decisions/concepts found within over the coming weeks.&lt;/p&gt;
&lt;p&gt; It's not perfect, it's not anywhere near done and as I keep telling people, it's just for reference purposes (at present), feel free to make suggestions, contributions and etc and we'll get there in the end. Multi-tenancy is the future you know?&lt;/p&gt;&lt;img src="http://blog.codeofrob.com/aggbug/8.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2010/01/31/ddd8-post-event.aspx</guid>
            <pubDate>Sun, 31 Jan 2010 18:01:55 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/8.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2010/01/31/ddd8-post-event.aspx#feedback</comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/8.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/8.aspx</trackback:ping>
        </item>
        <item>
            <title>NUnit 2.5.3 and [SetUICulture]</title>
            <link>http://blog.codeofrob.com/archive/2009/12/18/nunit-2.5.3-and-setuiculture.aspx</link>
            <description>&lt;p&gt;I can't for the life of me get this to work, and [SetCulture] appears to be working fine - so I can only assume it's a bug.&lt;/p&gt;
&lt;p&gt;I've posted to the mailing list and started off the process of working out whether it is a bug or not, but for now - I need to have my tests running  in the right culture, without any side effects on the other tests once a test has been complete.&lt;/p&gt;
&lt;p&gt;Here is my hack to do that:&lt;/p&gt;
&lt;pre class="brush: csharp;" title="code"&gt;   public class CultureContext : IDisposable
    {
        private CultureInfo mOldCulture;

        public CultureContext(String cultureName)
        {
            mOldCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
            System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
        }

        public void Dispose()
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = mOldCulture;
        }
    }&lt;/pre&gt;
&lt;p&gt;The usage is as follows, within a test do:&lt;/p&gt;
&lt;pre class="brush: csharp;" title="code"&gt;using (new CultureContext("fr-FR"))
{
	// Test code here
}&lt;/pre&gt;
&lt;p&gt;This will ensure that your test runs with the ui culture of "fr-FR", before resetting it to whatever it was before the test began. Not pretty, but it'll do until I work out if it's user error or a bug preventing NUnit from doing what I want it to do!&lt;/p&gt;&lt;img src="http://blog.codeofrob.com/aggbug/6.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2009/12/18/nunit-2.5.3-and-setuiculture.aspx</guid>
            <pubDate>Fri, 18 Dec 2009 14:28:11 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/6.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2009/12/18/nunit-2.5.3-and-setuiculture.aspx#feedback</comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/6.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/6.aspx</trackback:ping>
        </item>
        <item>
            <title>DDD8</title>
            <link>http://blog.codeofrob.com/archive/2009/12/11/ddd8.aspx</link>
            <description>&lt;p&gt;Developer Developer Developer Day 8 has been announced, and I'm going to propose a couple of sessions, and hopefully use one of them to talk about an open source project I've been cooking for a month or so now :)&lt;/p&gt;

&lt;p&gt;Click &lt;a href="http://developerdeveloperdeveloper.com/ddd8/Default.aspx"&gt;here&lt;/a&gt; for details!&lt;/p&gt;&lt;img src="http://blog.codeofrob.com/aggbug/5.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2009/12/11/ddd8.aspx</guid>
            <pubDate>Fri, 11 Dec 2009 11:56:39 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/5.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2009/12/11/ddd8.aspx#feedback</comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/5.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/5.aspx</trackback:ping>
        </item>
        <item>
            <title>Legacy .NET 1.1 COM in a classic ASP application after installing the .NET 2.0 Runtime</title>
            <link>http://blog.codeofrob.com/archive/2009/10/28/legacy-net-1.1-classic-asp-com-net-2.0-runtime-createobject.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;I've just had a fun evening trying to come up with a half-suitable solution for this problem and thought it worth documenting here although my next entry isn't due for a couple of days.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;As previously mentioned, we run a legacy classic ASP system for most of our clients and we're in the process of writing a replacement system in .NET.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;This week we finished the user acceptance testing  on the first deployable .NET application - a small interface built as a replacement for a small portion of that classic ASP system and needed therefore to build it to a live server.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The servers are fairly locked down as you'd expect and a change request had to be submitted to get .NET Framework 3.5 installed along with the .NET 2.0 runtime. I installed some routine security updates at the same time and rebooted the servers one at a time whilst testing that the legacy sites still worked.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;All seemed great until the next day when a very tired CTO turned up asking if he could get some sleep tonight because he had been receiving Nagios alerts all night telling him that the live sites were failing over. &lt;br /&gt;
Looking at the logs we could see that the application pools for most of the legacy sites had been recycling every hour and freezing for a vast majority of that hour - and with a bit of creative debugging the problem was isolated to the CreateObject calls to a pile of both in-house and third party managed COM objects installed on the server. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Rather than failing gracefully and logging an error, for some reason the calls were simply backing the server up and causing it to stop responding to requests.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I had a hunch that this was to do with the new version of the runtime we had installed and set about trying to prove that this was the case.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When an un-managed process (in this case our IIS worker process) is started up, it is obviously done so without initializing the .NET framework. If you then attempt to load a managed assembly into that process (in this case our COM object), the most recent version of the framework will be loaded into that process.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;At the moment, only one version of the .NET Framework is capable of being loaded into a single process, and this is determined on a first come first served basis.  99% of the time if you load a .NET 1.1 assembly into a .NET 2.0 process,  things will work fine because there are few breaking changes between the two runtimes - however there are cases where this does not hold true and as people always say "your mileage may vary".&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;In IIS, the application was set up as being a .NET 1.1 website - but I wasn't convinced that this had much to do with anything and decided to try out a little hack based on my previous experience with desktop application development, COM and the different .NET runtimes.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;When you deploy a .NET application, you can supply a configuration file with various overrides/version-mappings/etc alongside that application with the convention &amp;lt;applicationname&amp;gt;.exe.config. This means that you can also supply a configuration file for an application you don't "own" and modify that way it works on your machine.&lt;/font&gt;&lt;/p&gt;
&lt;pre class="brush: xhtml;" title="code"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;configuration&amp;gt;
 &amp;lt;startup&amp;gt;
 &amp;lt;supportedRuntime version="v1.1.4322"/&amp;gt;
 &amp;lt;requiredRuntime version="v1.1.4322"/&amp;gt;
 &amp;lt;/startup&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Some of the suggestions on the internet were to stick this in a web.config file at application root, but:&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;ol&gt;
    &lt;li&gt;I've read elsewhere that this is not supported in web applications  &lt;/li&gt;
    &lt;li&gt;I had a feeling that this directive would be ignored because the web.config file would only be read when a .NET resource was requested. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I decided that my nail was much bigger, and instead created an inetsrv.exe.config, a w3wp.exe.config and a dllhost.exe.config with the above directive in and placed them in system32/inetsrv and system32 respectively. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Restarting IIS and hitting my test page with all the CreateObjects (my fail case) yielded in a success and my next step was therefore going to be to find something that didn't involve forcing all IIS processes and god knows what else to run with .NET 1.1 and .NET 1.1 only. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;As previously mentioned, which runtime loaded into the worker process depends entirely on who first requests that a .NET assembly be loaded into process. The alternative in the desktop world and certain other places would be to manually invoke the .NET runtime with an explicit call to CorBindToCurrentRuntime  or similar.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I decided the best approach would be to force the IIS worker process to do this for me by invoking some .NET code in the context of the application. This would then use the framework version specified in the application and solve all the problems.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;&lt;br /&gt;
A few options were considered such as:&lt;/font&gt;&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;font face="Arial"&gt;Creating a global.asax to get executed when application starts&lt;/font&gt; &lt;font face="Arial" /&gt;&lt;/li&gt;
    &lt;li&gt;Creating a web.config file as outlined in a few of the responses to questions like this on the internet &lt;/li&gt;
    &lt;li&gt;Creating a dummy aspx file which could be requested by global.asa on application startup &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;font face="Arial"&gt;1 and 2 wouldn't work because no requests are ever made to the server through the aspnet extension, so 3 seemed to be the only reasonable solution.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The following aspx file was created on the server:&lt;/font&gt;&lt;/p&gt;
&lt;font face="Arial"&gt;
&lt;pre class="brush: xhtml;" title="code"&gt;&amp;lt;%@ Page Language="vb" AutoEventWireup="false" %&amp;gt;

&amp;lt;p&amp;gt;Hello World&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And the following code added to global.asa:&lt;/p&gt;
&lt;/font&gt;
&lt;pre class="brush: xhtml;" title="code"&gt;if not Application("hasInitializedNet") then

	Dim reqUrl 
	reqUrl = "http://" &amp;amp; Request.ServerVariables("LOCAL_ADDR") &amp;amp; "/default.aspx"

	Dim objXmlHttp
	Dim strHTML

	Set objXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")

	objXmlHttp.open "GET", reqUrl , False

	objXmlHttp.send

	strHTML = objXmlHttp.responseText
	
	Set objXmlHttp = nothing

	Application("hasInitializedNet") = true

end if&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;The application was restarted and voila, the page was requested when the first user hit the server and the right version of.NET was loaded into the application from the start.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;I can't think of a neater way that would allow us to still have our .NET 3.5 applications on the same machine and this solution is good enough for now (Until we get another pair of servers in for the new systems). &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Arial"&gt;Feel free to leave any better suggestions in the comments!&lt;/font&gt;&lt;/p&gt;
&lt;p /&gt;&lt;hr /&gt;
Technorati tags: &lt;a rel="tag" href="http://technorati.com/tags/COM"&gt;COM&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tags/ASP.NET"&gt;ASP.NET&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tags/.NET+Runtime"&gt;.NET Runtime&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tags/ASP"&gt;ASP&lt;/a&gt;
&lt;/font&gt;&lt;img src="http://blog.codeofrob.com/aggbug/3.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Ashton</dc:creator>
            <guid>http://blog.codeofrob.com/archive/2009/10/28/legacy-net-1.1-classic-asp-com-net-2.0-runtime-createobject.aspx</guid>
            <pubDate>Wed, 28 Oct 2009 23:32:47 GMT</pubDate>
            <wfw:comment>http://blog.codeofrob.com/comments/3.aspx</wfw:comment>
            <comments>http://blog.codeofrob.com/archive/2009/10/28/legacy-net-1.1-classic-asp-com-net-2.0-runtime-createobject.aspx#feedback</comments>
            <wfw:commentRss>http://blog.codeofrob.com/comments/commentRss/3.aspx</wfw:commentRss>
            <trackback:ping>http://blog.codeofrob.com/services/trackbacks/3.aspx</trackback:ping>
        </item>
    </channel>
</rss>