Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Autofac inject dependencies into layout view files?

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.

like image 809
Josh Avatar asked Jul 21 '12 15:07

Josh


People also ask

What is Autofac dependency injection?

Autofac is an open-source dependency injection (DI) or inversion of control (IoC) container developed on Google Code. Autofac differs from many related technologies in that it sticks as close to bare-metal C# programming as possible.

What is the use of Autofac in MVC?

AutoFac provides better integration for the ASP.NET MVC framework and is developed using Google code. AutoFac manages the dependencies of classes so that the application may be easy to change when it is scaled up in size and complexity.


2 Answers

Most of solutions will be just a wrapper around DependencyResolver.Current.GetService call, so it might be easier to call it directly from layout:

@{
    var helper = DependencyResolver.Current.GetService<IHelper>();
}
...
@if (helper.HasFoo()) { @Html.ActionLink("Bar") }
...

Also this way helps to make page model more SRP, because can avoid mixing service routines/models and business ones.

like image 126
Stan Avatar answered Oct 13 '22 10:10

Stan


Here is a little work around that will work with most DI frameworks.

First adjust you CustomPageView a little bit:

public abstract class CustomViewPage : WebViewPage
{
    public IHelper Helper { 
        get { return ViewData[Helper.ViewDataKey] as IHelper; }    
    }

}

Now well need to get the dependancy into your ViewData, introduce an attribute to do this:

public sealed class HelperAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var viewResult = filterContext.Result as ViewResult;
        if (viewResult != null)
            viewResult.ViewData.Add(Helper.ViewDataKey, GetHelperFromIoC());

        base.OnResultExecuting(filterContext);
    }
}

On you action method or controller:

[Helper]
public ActionResult Index()
{
    return View();
}

And in your view you should now be able to use your Helper as expected:

 @Helper.HelloWorld()

See this blog for the original post.

like image 1
shenku Avatar answered Oct 13 '22 11:10

shenku