Can Autofac inject dependencies into layout view f

2019-02-08 09:52发布

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.

5条回答
做个烂人
2楼-- · 2019-02-08 09:57

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.

查看更多
smile是对你的礼貌
3楼-- · 2019-02-08 09:59

Just create partial page and insert it into layout page:

@Html.Partial("_MyPartialPage");

Dependencies are injected into partial pages.

查看更多
在下西门庆
4楼-- · 2019-02-08 10:01

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.

查看更多
We Are One
5楼-- · 2019-02-08 10:14

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.

查看更多
Viruses.
6楼-- · 2019-02-08 10:18

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.

查看更多
登录 后发表回答