Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 340
DanAbdn Avatar asked Feb 06 '14 21:02

DanAbdn


People also ask

How do I get Autofac containers?

From Visual Studio, you can get it via NuGet. The package name is Autofac. Alternatively, the NuGet package can be downloaded from the GitHub repository (https://github.com/autofac/Autofac/releases).


1 Answers

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();     } } 
like image 155
DanAbdn Avatar answered Sep 22 '22 06:09

DanAbdn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!