I'm trying to inject a dependency into the shared layout view page to avoid having to do it in every view that uses the layout.
I've followed the guidance in the wiki for injecting dependencies into views, but the property is always null.
Can Autofac inject properties into a custom view page that is a layout file?
Here's my setup. CustomViewPage
namespace MyApp
{
using System.Web.Mvc;
public abstract class CustomViewPage : WebViewPage
{
public IHelper Helper { get; set; }
}
}
~/Views/Shared/_Layout.cshtml
@inherits MyApp.CustomViewPage
<!DOCTYPE html>
<html>
...
@if(this.Helper.HasFoo()){@Html.ActionLink("Bar")}
Global Registration...
builder.RegisterType<Helper>().AsImplementedInterfaces();
builder.RegisterModelBinderProvider();
builder.RegisterFilterProvider();
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterSource(new ViewRegistrationSource());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
The "child" views that use the layout do NOT derive from the CustomViewPage.
For result with no parameters you don't need to extend your WebViewPage to pass data to. I would solve it this way: 1. Declare a class HelperActionFilter derived from ActionFilter, inject your service to it via property http://docs.autofac.org/en/latest/integration/mvc.html 2. Inside HelperActionFilter.OnActionExecuting setup ViewBag.HasFoo check it in layout.
Just create partial page and insert it into layout page:
Dependencies are injected into partial pages.
It's not only with AutoFac basically you can't achieve DI in layouts. You may need a reference to the IOC Container in
CustomViewPage
to resolve the dependencies.Unless it's REALYYY REQUIRED just avoid DI in views (just my opinion).
From my point of view I don't see much benefits. I think you are not going to write unit tests for the base view page class do you? unless there is any special reason just avoid it. Instead of having dependency with the container it's better to have dependencies with concrete implementations.
Most of solutions will be just a wrapper around DependencyResolver.Current.GetService call, so it might be easier to call it directly from layout:
Also this way helps to make page model more SRP, because can avoid mixing service routines/models and business ones.
Here is a little work around that will work with most DI frameworks.
First adjust you CustomPageView a little bit:
Now well need to get the dependancy into your ViewData, introduce an attribute to do this:
On you action method or controller:
And in your view you should now be able to use your Helper as expected:
See this blog for the original post.