Can Autofac inject dependencies into layout view files?

家住魔仙堡 提交于 2020-01-21 02:50:12

问题


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.


回答1:


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.




回答2:


Just create partial page and insert it into layout page:

@Html.Partial("_MyPartialPage");

Dependencies are injected into partial pages.




回答3:


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.




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/11593580/can-autofac-inject-dependencies-into-layout-view-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!