Feb 27 2009

Using StructureMap with the ASP.NET MVC framework

Category: Uncategorizedbengtbe @ 06:13

In this post I will try to show you how to use StructureMap with the new ASP.NET MVC framework. You will need to have some basic knowledge about the ASP.NET MVC framework and Dependency Injection (DI)/Inversion of Control (IoC). The method described is not limited to StructureMap; if you prefer, you can of course use another DI/IoC tool.

The example starts with a UserController that has an dependency to a IUserService in the business layer, which again has a dependency to a IUserRepository in the database layer. The UserController uses inversion of control in regards to the IUserService. This means that the concrete UserService class must be injected into the UserController through the constructur:

public class UserController : Controller

{

    private readonly IUserService m_UserService;

 

    public UserController(IUserService userService)

    {

        m_UserService = userService;

    }

 

    public ActionResult Edit(int id)

    {

        return View(m_UserService.GetById(id));

    }

}

This is also called constructor injection. If you try to access this controller in the ASP.NET MVC framework you will get the following error:

No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object. 

By default, the ASP.NET MVC framework requires a parameterless constructor in the controllers. One way to fix this is to add a parameterless constructor:

public UserController() : this(new UserService(new UserRepository()))

{

}

This constructor is calling the other constructor using this passing in it's dependencies. Overloading the constructor in this manner is sometimes called Poor Man's Dependency Injection. It is a valid approach if you don't have access to an DI/IoC tool.

The downside of this approach is that you create a tight coupling between the controller and a concrete implementation of IUserService. You also have to take care of the dependencies (UserRepository) of the UserService class. Hence, the controller in the presentation layer now has a direct dependency to the UserRepository in database layer. If the UserRepository also had some dependencies then it really would start to get ugly :)

Let's fix this by using StructureMap's ObjectFactory to get an instance of IUserService.

public UserController() : this(ObjectFactory.GetInstance<IUserService>())

{

}

Much cleaner! The direct dependencies are now gone. However, every controller in your ASP.NET MVC application now needs to have an extra parameterless constructor and an reference to the ObjectFactory. This is just plumbing code, let's see if we can get rid of it all together.

The ASP.NET MVC framework uses the factory pattern to create controllers, and it also provides a base class called DefaultControllerFactory that you can derive from to customize the creation of controllers:

public class StructureMapControllerFactory : DefaultControllerFactory

{

    protected override IController GetControllerInstance(Type controllerType)

    {

        if(controllerType == null) return null;

 

        try

        {

            return ObjectFactory.GetInstance(controllerType) as Controller;

        }

        catch (StructureMapException)

        {

            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());

            throw;

        }

    }

}

The GetControllerInstance method is called when the framework needs a controller, specifed by its type. The code then asks StructureMap's ObjectFactory to create the controller. Since the controller is a concrete class (not an interface), it doesn't need to be configured with StructureMap. StructureMap will manage to create an instance of the controller and resolve all it's dependencies.

Now we have to tell the ASP.NET MVC framework to use the StructureMapControllerFactory. You can do this in the Application_Start method in Global.asax.cs:

protected void Application_Start()

{

    RegisterRoutes(RouteTable.Routes);

 

    StructureMapConfiguration.Configure();

 

    ControllerBuilder.Current.SetControllerFactory(new

       StructureMapControllerFactory());

}

As you can see the last line tells the framework to use the new factory. You can now remove the parameterless constructor, and the reference to StructureMap in the controllers.

Configuration of StructureMap

The second line in the Application_Start method is the configuration of StructureMap. This is done using the awesome new fluent configuration; no XML-configuration is needed!

public class StructureMapConfiguration

{

    public static void Configure()

    {

        ObjectFactory.Initialize(InitializeStructureMap);

    }

 

    private static void InitializeStructureMap(IInitializationExpression x)

    {

        x.Scan(y =>

                   {

                       y.Assembly("MvcWithNHibernate.Repositories");

                       y.Assembly("MvcWithNHibernate.Services");

                       y.With<DefaultConventionScanner>();

                   }

            );

    }

}

As you can see this uses the DefaultConventionScanner. This scanner uses a naming convention to automatically register the class UserService with the the interface IUserService, and the class UserRepository with IUserRepository.

Summary

In this post I have shown you how to use StructureMap with the new ASP.NET MVC framework. I described how you can implement your own controller factory to reduce the plumbing code in the controllers. When I first started to use StructureMap I had several calls to ObjectFactory.GetInstance throughout the solutions. A much better approach is to reduce these calls as much as possible. In this solution the only call to ObjectFactory.GetInstance is in the controller factory.

I also gave you a short glimpse of how you could configure StructureMap using the new fluent configuration and the default convention scanner. This follows the Convention over Configuration (CoC) paradigm made popular by Ruby on Rails. By following strict naming conventions, you don't need to configure the specific interfaces and classes with the DI/IoC tool, they are automatically added based on the conventions. In StructureMap you can also create your own auto register conventions.

kick it on DotNetKicks.com   Shout it

Tags: ,

12 Responses to “Using StructureMap with the ASP.NET MVC framework”

  1. bengtbe says:

    Just a correction I think you do not have to do this, SM automatically injects it:
    public UserController() : this(ObjectFactory.GetInstance<IUserService>())

    Thanks for your comment Kazi. I do belive that you have to call the parameterless constructor at that point, because it is not StructureMap that creates the controller, it’s the ASP.NET MVC framework. After we have created the StructureMapControllerFactory then we no longer need it, as I also write:

    You can now remove the parameterless constructor, and the reference to StructureMap in the controllers.

    Please correct me if you still think I’m wrong :)

  2. Kazi Manzur Rashid says:

    Just a correction I think you do not have to do this, SM automatically injects it:
    public UserController() : this(ObjectFactory.GetInstance<IUserService>())

  3. Kazi Manzur Rashid says:

    Sorry I have missed that completely. Great Article.

  4. Sandy says:

    I’ve followed your code, but i’m getting error message "StructureMap Exception Code: 202. No Default Instance defined for PluginFamily" when click http://localhost:54496/Account/LogOn

  5. bengtbe says:

    Hi Sandy,

    The reason you see that error is because you are using the default AccountController that follows the ASP.NET MVC project. This controller has two constructors:

    1. An empty (takes zero arguments):

    public AccountController() : this(null, null)

    2. One that take two arguments:

    public AccountController(IFormsAuthentication formsAuth, IMembershipService service)

    By default ASP.NET MVC will use the empty constructor (the other is used by the tests that follows the project). StructureMap however will, by default, use the constructor with the most parameter, but no one has told it how to resolve the parameters.

    You can fix this in 3 different ways:

    1. Tell StructureMap how to resolve those parameters in InitializeStructureMap:

    x.ForRequestedType<IFormsAuthentication>()
    .TheDefaultIsConcreteType<FormsAuthenticationService>();

    x.ForRequestedType<IMembershipService>()
    .TheDefaultIsConcreteType<AccountMembershipService>();

    x.ForRequestedType<MembershipProvider>()
    .TheDefault.IsThis(Membership.Provider);

    2. Tell StructureMap to use the empty constructor in InitializeStructureMap:

    x.ForRequestedType<AccountController>()
    .TheDefault.Is.ConstructedBy(() => new AccountController());

    3. Mark the empty controller with the DefaultConstructor attribute:

    [StructureMap.DefaultConstructor]
    public AccountController() : this(null, null)
    {
    }

    Just choose the fix that you like the most :)

  6. Sandy says:

    Yes, it’s working.
    Thank you, Sir.

  7. paul says:

    Do you ever offer download code samples? That would be great as most examples on the web are "Demo code" and leave out all the important stuff.

    Thanks

  8. Bengt Berge says:

    Hi Paul. I haven’t offered any code samples yet, but maybe I will in the future. I agree that there is to much "Demo code" on the web.

    If you want to check out some good ASP.NET MVC code then you might want to check out the following projects:

    CodeCampServer: http://code.google.com/p/codecampserver
    CodeBetter Canvas: http://code.google.com/p/codebettercanvas/
    Sharp Architecture: http://wiki.sharparchitecture.net

  9. paul says:

    Thanks for the reply Bengt. I have started reading Pro ASP.NET MVC Framwork but it uses L2S in all the examples similar to nerddinner. He also uses an IoC that requires XML mapping and after reading this post I am starting to think the book in out dated??? Have you read this book?

    Thanks for the code examples I will definitely check them out :)

    -Paul

  10. Bengt Berge says:

    Hi again Paul. I have read the book by Steven Sanderson and it is actually very good. It will give you a very good understanding of the ASP.NET MVC framework. In the book he uses the Castle Windsor IoC container, and this container does also support configuration with C# code. A search for "Castle Windsor" and "Fluent" will give you some examples of this.

    If you like the code in CodeCampServer then you can also check out the ASP.NET MVC in Action book. I believe that this code was written for this book. I’m planning to read it soon.

  11. Paul says:

    Thanks for the info. I think I am going to use StructureMap and nHibernate for the examples in the book as I don’t really want to learn L2S. I am also reading Microsoft .NET: Architecting Applications for the Enterprise and enjoying it. Thanks again for the info.

Leave a Reply