On the Extensibility of ASP.Net MVC

Much of the early hype surrounding the ASP.Net MVC framework revolved around the ability to use your dependency injection/inversion of control container of choice for resolving controllers at runtime.  The MvcContrib project already has implementations for Windsor, Spring, and StructureMap with ObjectBuilder soon to follow.  The framework also allows developers to use view rendering technologies other than the built in WebForms ViewPage.  The MvcContrib project already has an NVelocity view renderer thanks to Hammett.  I'm writing this post to try and influence, Scott, Phil, Rob, and Eilon to take the extensibility to the next level. 

What I am proposing is nothing radical and adds less than 10 lines of code to the existing implementation.  This is the right time to throw out suggestions since this is only the first CTP and there are areas that are obviously 'under construction.'  Even with all of the extensible points of the framework, I still see an awful lot of Activator.CreateInstance littered throughout the code.  Take the IControllerFactory for instance.  This is hailed as an extensibility point allowing you to supply your own implementation and thus have control over the creation of controllers.  It does deliver on its promise however, the framework instantiates a controller factory per request.  What if I want to reuse a controller factory?  Or what if my controller factory has dependencies on other classes or logic?  Why not let me, the developer, be in charge of providing you with an IControllerFactory when you need one?  But how, you ask, can this be achieved without disrupting the space-time continuum?  It's actually much simpler than you think.

The changes I propose affect HttpContextWrapper2.  You know this is a work in progress because (I seriously hope) Microsoft would not ship a class with that name (MvcContext maybe?).  As an aside, whatever you guys finally choose can you please not make it internal sealed?  Is that really necessary?  But I digress.  So here are my changes to HttpContextWrapper2:

Before:

object IServiceProvider.GetService(Type serviceType)
{
  return ((IServiceProvider) this._context).GetService(serviceType);
}

After:

object IServiceProvider.GetService(Type serviceType)
{
  IServiceProvider provider = this.ApplicationInstance as IServiceProvider;
  if( provider != null )
  {
    object service = provider.GetService(serviceType);
    if( service != null )
    {
      return service;
    }
  }

  return ((IServiceProvider)this._context).GetService(serviceType);
}

As promised, a very simple change to the existing implementation.  But what did we gain?  Well, we now give the ApplicationInstance a crack at providing the requested type, rather than just redirecting to the underlying HttpContext.  What is the ApplicationInstance?  In your run of the mill web application, this is the class housed in Global.asax.cs.  So, with the code snippet below, we could use the Windsor container as the service provider:

public class Global : HttpApplication, IServiceProvider
{
  private static WindsorContainer _container;

  public object GetService(Type serviceType)
  {
    if( _container.Kernel.HasComponent(serviceType) )
    {
      return _container.GetService(serviceType);
    }

    return null;
  }

  protected void Application_Start(object sender, EventArgs e)
  {
    // Initialize the container...
  }
}

Now the MVC framework can take advantage of the rich DI/IoC capabilities of Windsor (or any of the containers mentioned at the beginning of this article) without adding dependencies to it.  Just replace all of those Activator.CreateInstance(type) calls with context.GetService(type).  If the call to GetService returns null, then you can still resort to your own creation mechanisms.  But at least give us a chance to take control of the process if we so choose.

Unless I a missing something this should be a low impact, low risk modification to the existing framework with high rewards.

posted @ Sunday, December 16, 2007 4:18 PM


Print

Comments on this entry:

# Link Listing - December 16, 2007

Left by Christopher Steen at 12/16/2007 9:08 PM

Link Listing - December 16, 2007

# Link Listing - December 16, 2007

Left by Christopher Steen at 12/16/2007 9:08 PM

WPF Mole For Visual Studio Released [Via: Karl Shifflett ] Code Camps Code Camp 2008.1 Update [Via:...

# re: On the Extensibility of ASP.Net MVC

Left by Rob Conery at 12/18/2007 1:03 AM
Gravatar

Hey there- some thoughts for you :)

1) Always have an "About Me" somewhere so people know who you are, what you know, etc - it really helps :)

2) You're very right - now is the time to come up with ideas

3) I forwarded this link to Phil

4) Please come (if you haven't) to the forums and let us know a bit more...

Thank you for this - it's good stuff!

# Temp service provider implementation

Left by My Head's Exploding at 12/18/2007 9:06 AM

Temp service provider implementation

Your comment:



 (will not be displayed)


 
 
 
Please add 1 and 7 and type the answer here:
 

Live Comment Preview:

 
«July»
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789