Autofac始終保持最新,以支援最新版本的ASP.NET MVC,所以文檔也保持最新。 一般而言,各個版本的整合保持相當一致。
MVC整合需要Autofac.Mvc5 NuGet包。
MVC整合為控制器,模型繫結器,操作過濾器和視圖提供了依賴注入整合。 它也增加了每個請求生命週期的支援。
本頁解釋了ASP.NET經典MVC整合。 如果您正在使用ASP.NET Core,請參閱ASP.NET Core整合頁面。
Quick Start Register Controllers Set the Dependency Resolver Register Model Binders Register Web Abstractions Enable Property Injection for View Pages Enable Property Injection for Action Filters Enable Injection of Action Parameters OWIN Integration Using “Plugin” Assemblies Using the Current Autofac DependencyResolver Glimpse Integration Unit Testing Example
快速開始
要使Autofac與MVC整合,您需要引用MVC整合NuGet包,註冊您的控制器並設定依賴關係解析器。 您也可以選擇啟用其他功能。
protected void Application_Start(){ var builder = new ContainerBuilder(); //註冊您的MVC控制器。 (MvcApplication是Global.asax中類的名稱。) builder.RegisterControllers(typeof(MvcApplication).Assembly); //可選:註冊需要DI的模型繫結器 builder.RegisterModelBinders(typeof(MvcApplication).Assembly); builder.RegisterModelBinderProvider(); //可選:註冊Web抽象如HttpContextBase。 builder.RegisterModule<AutofacWebTypesModule>(); //可選:在視圖頁面中啟用屬性注入。 builder.RegisterSource(new ViewRegistrationSource()); //可選:啟用屬性注入到ation過濾器。 builder.RegisterFilterProvider(); //可選:啟用action 方法參數注入(RARE) builder.InjectActionInvoker(); //將依賴關係解析器設定為Autofac var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container));}
以下各節詳細介紹了每個功能的用途以及如何使用它們。 註冊控制器
在應用程式啟動時,在構建您的Autofac容器時,您應該註冊您的MVC控制器及其依賴項。 這通常發生在OWIN啟動類或Global.asax的Application_Start方法中。
var builder = new ContainerBuilder();//您可以使用程式集掃描一次註冊控制器...builder.RegisterControllers(typeof(MvcApplication).Assembly);//...或者您可以手動註冊個人控制器。builder.RegisterType<HomeController>().InstancePerRequest();
請注意,ASP.NET MVC通過其具體類型請求控制器,因此將其註冊為As<IController>()是不正確的。 另外,如果您手動註冊控制器並選擇指定生命週期,則必須將它們註冊為InstancePerDependency()或InstancePerRequest() - 如果您嘗試為多個請求重用控制器執行個體,ASP.NET MVC將引發異常。 設定依賴關係解析器
在構建你的容器之後,將它傳遞給AutofacDependencyResolver類的新執行個體。 使用靜態DependencyResolver.SetResolver方法讓ASP.NET MVC知道它應該使用AutofacDependencyResolver來定位服務。 這是Autofac的IDependencyResolver介面的實現。
var container = builder.Build();DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
You can do this with the RegisterModelBinders() method. You must also remember to register the AutofacModelBinderProvider using the RegisterModelBinderProvider() extension method. This is Autofac’s implementation of the IModelBinderProvider interface. 註冊模型繫結器
您可以採取的可選步驟是為模型繫結器啟用依賴項注入。與控制器類似,模型繫結器(實現IModelBinder的類)可以在應用程式啟動時在容器中註冊。 你可以用RegisterModelBinders()方法做到這一點。 您還必須記住使用RegisterModelBinderProvider()擴充方法註冊AutofacModelBinderProvider。 這是Autofac的IModelBinderProvider介面的實現。
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());builder.RegisterModelBinderProvider();
由於RegisterModelBinders()擴充方法使用程式集掃描來添加模型繫結器,所以您需要指定要註冊的模型繫結器(IModelBinder實現)的類型。
這是通過使用Autofac.Integration.Mvc.ModelBinderTypeAttribute完成的,如下所示:
[ModelBinderType(typeof(string))]public class StringBinder : IModelBinder{ public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { //在這裡實現 }}
ModelBinderTypeAttribute的多個執行個體可以被添加到一個類,如果它被註冊為多個類型的話。 註冊Web抽象
MVC整合套件括一個Autofac模組,它將為Web抽象類別添加HTTP請求生命週期的註冊。這將允許您將Web抽象作為依賴項放入您的類中,並在運行時擷取正確的注入值。
以下抽象類別包含在內:
HttpContextBase HttpRequestBase HttpResponseBase HttpServerUtilityBase HttpSessionStateBase HttpApplicationStateBase HttpBrowserCapabilitiesBase HttpFileCollectionBase RequestContext HttpCachePolicyBase VirtualPathProvider UrlHelper
要使用這些抽象,請使用標準RegisterModule()方法將AutofacWebTypesModule添加到容器中。
builder.RegisterModule<AutofacWebTypesModule>();
為視圖頁啟用屬性注入
通過在構建應用程式容器之前將ViewRegistrationSource添加到ContainerBuilder,可以使屬性注入可用於您的MVC視圖。
builder.RegisterSource(new ViewRegistrationSource());
您的視圖頁面必須從MVC支援建立視圖的基類之一繼承。當使用Razor視圖引擎時,這將是WebViewPage類。
public abstract class CustomViewPage : WebViewPage{ public IDependency Dependency { get; set; }}
使用web forms視圖引擎時,ViewPage,ViewMasterPage和ViewUserControl類都受支援。
public abstract class CustomViewPage : ViewPage{ public IDependency Dependency { get; set; }}
確保您的實際視圖頁面從您的自訂基類繼承。這可以使用Razor視圖引擎的.cshtml檔案中的@inherits指令來實現:
@inherits Example.Views.Shared.CustomViewPage
在使用 web forms視圖引擎時,請在.aspx檔案中的@Page指令中設定Inherits屬性。
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Example.Views.Shared.CustomViewPage"%>
由於ASP.NET MVC內部的問題,依賴注入不可用於Razor布局頁面。Razor視圖將工作,但布局頁面不會。有關更多資訊,請參閱問題#349。 為Action篩選器啟用屬性注入
在構建容器並將其提供給AutofacDependencyResolver之前,要為您的過濾器屬性使用屬性注入,請調用ContainerBuilder上的RegisterFilterProvider()方法。
builder.RegisterFilterProvider();
這允許您將屬性添加到您的過濾器屬性中,並且在容器中註冊的任何匹配依賴項將被注入到屬性中。
例如,下面的動作過濾器將從容器中注入ILogger執行個體(假設你註冊了一個ILogger,注意該屬性本身不需要在容器中註冊。
public class CustomActionFilter : ActionFilterAttribute{ public ILogger Logger { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { Logger.Log("OnActionExecuting"); }}
相同的簡單方法適用於其他過濾器屬性類型,例如授權屬性。
public class CustomAuthorizeAttribute : AuthorizeAttribute{ public ILogger Logger { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { Logger.Log("AuthorizeCore"); return true; }}
像往常一樣將屬性應用到您的actions 之後,您的工作就完成了。
[CustomActionFilter][CustomAuthorizeAttribute]public ActionResult Index(){}啟用注入Action參數
雖然不常見,但有些人希望Autofac在調用時在操作方法中填充參數。 建議您在控制器上使用建構函式注入而不是action方法注入,但是如果需要,可以啟用操作方法注入:
//Autofac ExtensibleActionInvoker嘗試從請求生命週期範圍解析參數如果模型繫結器無法綁定到參數。builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();builder.InjectActionInvoker();
請注意,您也可以使用InjectActionInvoker()機制與您自己的自訂調用程式。
builder.RegisterType<MyCustomActionInvoker>().As<IActionInvoker>();builder.InjectActionInvoker();
OWIN整合
如果您使用MVC作為OWIN應用程式的一部分,則需要: 做標準的MVC整合的所有東西 - 註冊控制器,設定依賴解析器等。 使用基礎Autofac OWIN整合設定您的應用程式。 添加對Autofac.Mvc5.Owin NuGet包的引用。 在您的應用程式啟動類中,在註冊基礎Autofac中介軟體後註冊Autofac MVC中介軟體。
public class Startup{ public void Configuration(IAppBuilder app) { var builder = new ContainerBuilder(); //標準MVC設定: //註冊您的MVC控制器。 builder.RegisterControllers(typeof(MvcApplication).Assembly); //運行其他可選步驟,如註冊模型繫結器,Web抽象等,然後將依賴關係解析器設定為Autofac。 var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //OWIN MVC設定: //先註冊Autofac中介軟體,然後註冊Autofac MVC中介軟體。 app.UseAutofacMiddleware(container); app.UseAutofacMvc(); }}
小問題:MVC在OWIN管道中不能運行100%。它仍然需要HttpContext.Current和其他一些非OWIN的東西。在應用程式啟動時,當MVC註冊路由時,它執行個體化一個IControllerFactory,最終建立兩個請求生存期範圍。它只發生在應用程式在路由註冊時啟動,而不是一旦請求開始得到處理,但它是要注意的事情。這是兩條管道被碾壓在一起的產物。我們研究了一些方法來嘗試解決這個問題,但卻無法以一種乾淨的方式來實現。 使用“外掛程式”程式集
如果你有一個“外掛程式程式集”中沒有被主應用程式引用的控制器,你將需要使用ASP.NET BuildManager註冊你的控制器外掛程式程式集。
你可以通過配置或者編程來完成。
如果選擇配置,則需要將外掛程式程式集添加到/configuration/system.web/compilation/assemblies列表中。如果您的外掛程式程式集不在bin檔案夾中,則還需要更新/configuration/runtime/assemblyBinding/probing路徑。
<?xml version="1.0" encoding="utf-8"?><configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- If you put your plugin in a folder that isn't bin, add it to the probing path --> <probing privatePath="bin;bin\plugins" /> </assemblyBinding> </runtime> <system.web> <compilation> <assemblies> <add assembly="The.Name.Of.Your.Plugin.Assembly.Here" /> </assemblies> </compilation> </system.web></configuration>
如果選擇編程註冊,則需要在ASP.NET BuildManager啟動之前的預應用程式啟動期間執行。
建立一個初始化類來執行程式集掃描/載入和註冊BuildManager:
using System.IO;using System.Reflection;using System.Web.Compilation;namespace MyNamespace{ public static class Initializer { public static void Initialize() { var pluginFolder = new DirectoryInfo(HostingEnvironment.MapPath("~/plugins")); var pluginAssemblies = pluginFolder.GetFiles("*.dll", SearchOption.AllDirectories); foreach (var pluginAssemblyFile in pluginAssemblyFiles) { var asm = Assembly.LoadFrom(pluginAssemblyFile.FullName); BuildManager.AddReferencedAssembly(asm); } } }}
然後確保使用程式集屬性註冊您的應用程式之前的開始代碼:
[assembly: PreApplicationStartMethod(typeof(Initializer), "Initialize")]
使用當前的Autofac DependencyResolver
一旦將MVC DependencyResolver設定為AutofacDependencyResolver,就可以使用AutofacDependencyResolver.Current作為擷取當前依賴項解析器並將其轉換為AutofacDependencyResolver的捷徑。
不幸的是,在使用AutofacDependencyResolver.Current時會遇到一些問題,這可能會導致不正確的工作。通常,這些問題通過使用像Glimpse或Castle DynamicProxy這樣的產品來“封裝”或“裝飾”依賴解析器來添加功能。如果當前的依賴關係解析器被裝飾或以其他方式進行封裝/代理,則不能將其轉換為AutofacDependencyResolver,並且沒有單獨的方法來“解包”或轉到實際的解析器。
在Autofac MVC整合版本3.3.3之前,我們通過動態地將它添加到請求生命週期範圍來跟蹤當前的依賴關係解析器。這讓我們無法從代理中解開AutofacDependencyResolver,但是這意味著AutofacDependencyResolver.Current只能在請求生命期內工作 - 不能在背景工作或應用程式啟動時使用它。
從版本3.3.3開始,定位AutofacDependencyResolver.Current的邏輯改為首先嘗試轉換當前的依賴關係解析器;然後專門尋找使用Castle DynamicProxy封裝的標誌,並通過反射將其開啟。沒有這個…我們找不到當前的AutofacDependencyResolver,所以我們拋出一個InvalidOperationException異常,
依賴關係解析器的類型是“Some.Other.DependencyResolver”,但預計是“Autofac.Integration.Mvc.AutofacDependencyResolver”類型。它也不會被Castle Project中的DynamicProxy所封裝。這個問題可能是DynamicProxy實現發生變化的結果,也可能是由於使用了不同的代理庫來封裝依賴關係解析器。
這是典型的地方,當通過ContainerBuilder.RegisterFilterProvider()使用動作過濾器提供者時。篩選器提供者需要訪問Autofac依賴關係解析器並使用AutofacDependencyResolver.Current來執行此操作。
如果你看到這個,這意味著你正在用一種無法解開的方式裝飾解析器,而依賴於AutofacDependencyResolver.Current的函數將會失敗。目前的解決方案是不裝飾依賴解析器。 Glimpse 整合
使用Autofac時,將MVC應用程式與Glimpse整合在一起與其他任何整合都非常相似。 但是,如果使用動作方法參數注入(例如,使用builder.InjectActionInvoker()),則Glimpse執行檢查將失敗。
您可以通過將以下內容添加到Glimpse配置來解決此問題:
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd"> <inspectors> <ignoredTypes> <add type="Glimpse.Mvc.Inspector.ExecutionInspector, Glimpse.Mvc"/> </ignoredTypes> </inspectors> <tabs> <ignoredTypes> <add type="Glimpse.Mvc.Tab.Execution, Glimpse.Mvc"/> </ignoredTypes> </tabs></glimpse>
同樣,如果您使用action參數注入,則只需執行此操作。這是推薦使用控制器建構函式注入而不是action方法參數注入的許多原因之一。 單元測試
當單元測試一個使用Autofac的應用程式,並且你已經註冊了InstancePerRequest組件時,當你嘗試解析這些組件時,你會得到一個異常,因為在單元測試期間沒有HTTP請求生命週期。
每個請求生存期範圍主題概述了針對每個請求範圍組件進行測試和故障排除的策略。