How do I properly register AutoFac in a basic MVC5.1 website?

30,745

Here's what I have - feedback welcome!

Global.asax.cs:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // Register Inversion of Control dependencies
        IoCConfig.RegisterDependencies();

        // Typical MVC setup
        // ....
    }
}

App_Start folder:

public class IoCConfig
{

    /// <summary>
    /// For more info see 
    /// :https://code.google.com/p/autofac/wiki/MvcIntegration (mvc4 instructions)
    /// </summary>
    public static void RegisterDependencies()
    {
        #region Create the builder
        var builder = new ContainerBuilder();
        #endregion

        #region Setup a common pattern
        // placed here before RegisterControllers as last one wins
        builder.RegisterAssemblyTypes()
               .Where(t => t.Name.EndsWith("Repository"))
               .AsImplementedInterfaces()
               .InstancePerHttpRequest();
        builder.RegisterAssemblyTypes()
               .Where(t => t.Name.EndsWith("Service"))
               .AsImplementedInterfaces()
               .InstancePerHttpRequest();
        #endregion

        #region Register all controllers for the assembly
        // Note that ASP.NET MVC requests controllers by their concrete types, 
        // so registering them As<IController>() is incorrect. 
        // Also, if you register controllers manually and choose to specify 
        // lifetimes, you must register them as InstancePerDependency() or 
        // InstancePerHttpRequest() - ASP.NET MVC will throw an exception if 
        // you try to reuse a controller instance for multiple requests. 
        builder.RegisterControllers(typeof(MvcApplication).Assembly)
               .InstancePerHttpRequest();

        #endregion

        #region Register modules
        builder.RegisterAssemblyModules(typeof(MvcApplication).Assembly);
        #endregion

        #region Model binder providers - excluded - not sure if need
        //builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
        //builder.RegisterModelBinderProvider();
        #endregion

        #region Inject HTTP Abstractions
        /*
         The MVC Integration includes an Autofac module that will add HTTP request 
         lifetime scoped registrations for the HTTP abstraction classes. The 
         following abstract classes are included: 
        -- HttpContextBase 
        -- HttpRequestBase 
        -- HttpResponseBase 
        -- HttpServerUtilityBase 
        -- HttpSessionStateBase 
        -- HttpApplicationStateBase 
        -- HttpBrowserCapabilitiesBase 
        -- HttpCachePolicyBase 
        -- VirtualPathProvider 

        To use these abstractions add the AutofacWebTypesModule to the container 
        using the standard RegisterModule method. 
        */
        builder.RegisterModule<AutofacWebTypesModule>();

        #endregion

        #region Set the MVC dependency resolver to use Autofac
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        #endregion

    }

 }

Then you can register modules as you see fit which is really great if you have a modularised application and you don't know what you are going to include in your project. You can nuget setup your project and no manual intervention required (I wish!)....

public class RegisterApplicationIoC : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<EmailSenderToDebug>()
               .As<IEmailSender>()
               .InstancePerHttpRequest();
    }
}
Share:
30,745
DanAbdn
Author by

DanAbdn

Programmer based at Aberdeen, UK. Primarily interests relate around web technologies: MVC 6 with C# Single Page Applications (SPA) - Angular2 SignalR WebGL / OpenGL Visual Studio 2015

Updated on March 03, 2020

Comments

  • DanAbdn
    DanAbdn about 4 years

    AutoFac has recently been updated for MVC 5.1 but at the time of writing I find that the documentation is lacking (especially for a simple example).

    I would like to inject dependencies into MVC Controllers and register my own implementations for e.g. e-mail (actual sending vs print to output window) as a basic example.

    I'm do not know if I am missing a good resource for this and I am slight concerned that because it uses the OWIN specification that the implementation may differ for MVC5.1 (ASP.NET Identity uses OWIN and there is some special attributes used to properly instantiate OWIN) so need to check I am getting things right.

    I have a working example with the below setup code - is this correct and good practice for a standard MVC5.1 web app?

    Bonus question: do I need to add InstancePerHttpRequest to the RegisterControllers line? i.e. builder.RegisterControllers(typeof(MvcApplication).Assembly).InstancePerHttpRequest();

    (Note: I see the examples on GitHub from Autofac but cannot find an plain example appropriate to MVC5.1.)

    public static void RegisterDependencies()
    {
        // Register MVC-related dependencies
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterModelBinders(typeof(MvcApplication).Assembly);
        builder.RegisterModule<AutofacWebTypesModule>();
    
        // Register e-mail service
        builder.RegisterType<EmailSenderToDebug>().As<IEmailSender>().InstancePerHttpRequest();
    
        builder.RegisterModelBinderProvider();
    
        // Set the MVC dependency resolver to use Autofac
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
    

    And my controller:

    public class HomeController : Controller
    {
    
        public IEmailSender _email { get; set; }
    
        public  HomeController(IEmailSender es)
        {
            this._email = es;
        }
        //
        // GET: /Home/
        public ActionResult Index()
        {
    
            Email e = new Email();
            e.To(new MailAddress("[email protected]", "mr. something"));
            e.Subject("test");
            e.Message("hello world");
            e.From(new MailAddress("[email protected]", "mr. else"));
            this._email.SendEmail(e);
            return View();
        }
    }
    

    Thanks!

  • John Lieb-Bauman
    John Lieb-Bauman almost 10 years
    InstancePerHttpRequest was deprecated for AutoFac 3.4.0 and 4.0.0 the replacement being InstancePerRequest. See here
  • phougatv
    phougatv over 7 years
    Adding IoCConfig.RegisterDependencies(); to Global.asax asks me to add the respective namespace. On doing that I get the following error A reference to 'Bootstrapper' could not be added. Adding this project as a reference would cause a circular dependency. I know why of this error. What I want to know is how to resolve it?
  • phougatv
    phougatv over 7 years
    I was able to run it after moving my IocConfig.cs file to App_Start folder. Problem from my last comment was also solved. Now I want to know how to maintain the folder structure? What are the standards of creating folder/project structure while using autofac? Is there a way where I can place my IocConfig file in some other folder? Kindly provide links(if there are any).