First time here? You are looking at the most recent posts. You may also want to check out older archives or the tag cloud. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS. Thank you for visiting! (hide this)

Most of the mainstream IoC containers have their own implementation of a custom controller factory for ASP.NET MVC, but Unity doesn’t. There is an implementation in the MvcContrib project, but I don’t like the way it works, so I decided to implement it myself.

Unity Controller Factory

After a few mail exchanges with a guys of the p&p team and with Brad Wilson I came out with the following 35 lines of code.

public class UnityControllerFactory: DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        IController controller;
        if (controllerType == null)
            throw new HttpException(
                    404, String.Format(
                     "The controller for path '{0}' could not be found" +
			"or it does not implement IController.",
                     this.RequestContext.HttpContext.Request.Path));
        if (!typeof(IController).IsAssignableFrom(controllerType))
            throw new ArgumentException(
                    string.Format(
                        "Type requested is not a controller: {0}",
                        controllerType.Name),
                        "controllerType");
        try
        {
            controller = MvcUnityContainer.Container.Resolve(controllerType)
                            as IController;
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(String.Format(
                                    "Error resolving controller {0}",
                                    controllerType.Name),ex);
        }
        return controller;
    }
}

public static class MvcUnityContainer
{
    public static UnityContainer Container { get; set; }
}

And the only things needed to use it is creating the container, passing it to the controller factory, registering the dependencies (repositories, services) and finally setting the custom controller factory.

//Create UnityContainer
UnityContainer container = new UnityContainer();

//Configure container
container.RegisterType<IFrontendService, FrontendService>();
container.RegisterType<IDateTimeProvider, DateTimeProvider>();
container.RegisterType<IFrontendDataAccess, SqlFrontendDataAccess>();

//Set container for Controller Factory
MvcUnityContainer.Container = container;

//Set for Controller Factory
ControllerBuilder.Current.SetControllerFactory(
                    typeof(UnityControllerFactory));

Implementation possibilities

There are two possibilities when you want to write a custom controller factory:

  • Implement IControllerFactory and implement the CreateContoller method that returns a controller based on the controller name
  • Inherit from DefaultControllerFactory and override GetControllerInstance which returns a controller based on the type that is needed

The first gives you complete freedom on the naming conventions of your controllers, but has two downsides: first it needs you to register not only the external references but also the controllers (container.RegisterType<IController, HomeController>("Home")). Second you also have to implement the logic to discover the correct controller based on the namespace and, more importantly with MVC v2, with the Areas.

The second approach delegates to the default implementation the mapping of the controller name to the type of the controller. Less freedom with the naming convention, but also less code to write both in the controller factory and also during the setup of your application.

Applying the same concept to Ninject

I think the Ninject controller factory uses the first approach and might not work with Areas in MVC v2, so I think I’ll submit a patch to adopt this easier approach.

posted on Friday, December 11, 2009 3:09 PM

Comments on this entry:

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Slava at 12/13/2009 1:02 PM

Why you using this IOC container, there are a lot of better variants to do the same staff

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Wolfgang Maier at 12/13/2009 3:43 PM

@Slava
Please give me a list, of other (maybee better) IOC-Container.
I need one working with MVC2-Areas and it should be simple and lightweight.

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Simone at 12/13/2009 7:10 PM

@Slava: There are many IoC Containers, they all do the same stuff.
I usually prefer Ninject, but unfortunately you can't always choose what you prefer.
Welcome to the sad real world of "consulting" :)

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Wolfgang Maier at 12/14/2009 7:38 AM

@simone: I've tried with Ninject, because I found it very Easy to use, but it seems, that Ninject don't recognize same controllername in different areas in MVC2. Do you have a fix for it?

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Simone at 12/15/2009 7:27 PM

@Wolfgang: I know, Ninject doesn't work well with ASP.NET MVC2, for the reason I just highlighted in the post.
The only way to fix it is to re-implement the controller factory the way I just did for Unity.
I'll try to work on it if I find time :)

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Matt at 1/2/2010 12:39 AM

Hey,
that was a great post, however, there is an error in the code and it won't compile.
the signature of GetControllerInstance doesn't match any suitable methods to override. I believe the override you're looking for the one with the RequestContext passed in first then the type? in which case you also want to change the this.RequestContext.etc...

# re: ASP.NET MVC ControllerFactory for Unity and the reasoning behind it

Left by Lee Smith at 1/17/2010 1:54 AM

I've just created this project in codeplex: http://mvcunity.codeplex.com/

Hope it helps someone.

Comments have been closed on this topic.