MVC

Autofac总是会紧跟最新版本的ASP.NET MVC框架,所以文档也会一直保持更新。一般来讲,不同版本的框架集成Autofac的方法一般不变。

MVC集成需要引用 Autofac.Mvc5 NuGet包.

MVC 集成库提供对控制器(Controller)、模型绑定器(model binders)、行为筛选器(action filters)和视图(views)的依赖注入. 它也添了对 每次请求生命周期(per-request lifetime)的支持.

快速开始 Quick Start

为了将Autofac集成进MVC项目,你需要引用Autofac.MVC集成库,注册你的控制器以及设定依赖解析器。你也可以启用其他可选的特性。

protected void Application_Start()
{
var builder = new ContainerBuilder(); // Register your MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly); // OPTIONAL: Register model binders that require DI.
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider(); // OPTIONAL: Register web abstractions like HttpContextBase.
builder.RegisterModule<AutofacWebTypesModule>(); // OPTIONAL: Enable property injection in view pages.
builder.RegisterSource(new ViewRegistrationSource()); // OPTIONAL: Enable property injection into action filters.
builder.RegisterFilterProvider(); // Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

接下来的部分将说明关于这些特性进一步的细节以及如何使用它们。

注册控制器 Register Controllers

在应用程序启动时,你在构建自己的容器(ContainerBuilder)时, 也应该注册所有的控制器以及它们的依赖项. 这通常会发生在典型的OWIN启动类或者  Global.asax 的 Application_Start 方法中.

var builder = new ContainerBuilder();

// You can register controllers all at once using assembly scanning...
builder.RegisterControllers(typeof(MvcApplication).Assembly); // ...or you can register individual controlllers manually.
builder.RegisterType<HomeController>().InstancePerRequest();

注意,ASP.NET MVC通过实体类型来请求控制器实例,所以不能将他们注册为 As<IController>(). 同时,如果你手动注册控制器且选择定制生命周期,你必须将他们注册为InstancePerDependency() 或者 InstancePerRequest()- 在这种情况下,如果你尝试为多个请求重用一个控制器实例,ASP.NET MVC程序将会抛出异常

设定依赖解析器 Set the Dependency Resolver

在构建好容器后, 将他传入一个AutofacDependencyResolver 类的实例中. 使用静态方法 DependencyResolver.SetResolver 来使 ASP.NET MVC知道它应该使用 AutofacDependencyResolver 来定位服务(Service). 这是一个 IDependencyResolver 接口的Autofac实现.

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

注册模型绑定器 Register Model Binders

你可以使用的一个可选步骤是确保对模型绑定器的依赖注入。和注册控制器类似,模型绑定器(IModelBinder接口的实现类)能够在应用程序启动时注册进容器中。你可以使用 RegisterModelBinders() 方法来这样做。你同时也必须记住要使用 RegisterModelBinderProvider() 拓展方法注册 AutofacModelBinderProvider。这是一个 IModelBinderProvider 接口的Autofac实现。

builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();

由于 RegisterModelBinders() 方法采用集合(Assembly)扫描来添加模型绑定器,所以你需要指定模型绑定器为哪种类型注册。

可以通过 Autofac.Integration.Mvc.ModelBinderTypeAttribute 属性标签来指定,如下:

[ModelBinderType(typeof(string))]
public class StringBinder : IModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Implementation here
}
}

如果要注册为多个类型的模型绑定器,可以直接为类添加多个 ModelBinderTypeAttribute 标签。

注册网络抽象 Register Web Abstractions

MVC集成库包括了一个Autofac模块,这个模块能够为网络抽象类添加HTTP请求生命周期域的注册 . 这允许你将网络抽象作为你的类的依赖,同时能够在运行时获取注入的正确值(Value).

这包括了下面的抽象类:

  • HttpContextBase
  • HttpRequestBase
  • HttpResponseBase
  • HttpServerUtilityBase
  • HttpSessionStateBase
  • HttpApplicationStateBase
  • HttpBrowserCapabilitiesBase
  • HttpFileCollectionBase
  • RequestContext
  • HttpCachePolicyBase
  • VirtualPathProvider
  • UrlHelper

为了使用这些抽象类,通过使用标准的 RegisterModule() 方法来将 AutofacWebTypesModule 添加到容器中。

builder.RegisterModule<AutofacWebTypesModule>();

确保视图页面的属性注入 Enable Property Injection for View Pages

在构建应用容器之前,你可以通过将ViewRegistrationSource添加到你的ContainerBuilder使得可以在视图页中使用属性注入。

builder.RegisterSource(new ViewRegistrationSource());

你的视图页必须继承一个MVC用于创建视图的基类。在使用Razor视图引擎时,这时的基类是指WebViewPage类。

public abstract class CustomViewPage : WebViewPage
{
public IDependency Dependency { get; set; }
}

使用Web form引擎时,支持的基类为ViewPageViewMasterPage以及ViewUserControl

public abstract class CustomViewPage : ViewPage
{
public IDependency Dependency { get; set; }
}

确保你实际的视图页继承于你的自定义基类。对于Razor视图引擎,你可以直接在.cshtml文件中使用@Inherits来实现.

@inherits Example.Views.Shared.CustomViewPage

使用Web Form引擎时,你可以在.aspx文件中的@Page里直接设置Inherits属性来实现。

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Example.Views.Shared.CustomViewPage"%>

由于ASP.NET MVC内部的问题,在Razor Layout页面中是不能使用依赖注入的。Razor视图中则可以使用,但是布局页面是不可以的。

确保对行文筛选器的属性注入 Enable Property Injection for Action Filters

为了能够为你的筛选器属性使用属性注入,需要在构建容器并将容器提供为AutofacDependencyResolver之前调用ContainerBuilderRegisterFilterProvider()方法。

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;
}
}

在应用筛选器到你的action中,它会像正常一样工作。

[CustomActionFilter]
[CustomAuthorizeAttribute]
public ActionResult Index()
{
}

OWIN集成 OWIN Integration

如果你正在使用MVC作为OWIN程序的一部分,那么你需要做下面的事情:

  • 做完所有标准的MVC集成步骤-注册控制器,设置依赖解析器等等
  • 使用Autofac 基本OWIN集成步骤设置你的应用。
  • 添加对 Autofac.Mvc5.Owin 包的引用.
  • 在你的应用启动类中, 在注册完基本Autofac中间件后再注册Autofac MVC中间件.
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder(); // STANDARD MVC SETUP: // Register your MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly); // Run other optional steps, like registering model binders,
// web abstractions, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); // OWIN MVC SETUP: // Register the Autofac middleware FIRST, then the Autofac MVC middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
}

使用“插件”集合 Using “Plugin” Assemblies

如果你在一个插件集合中有没有被主程序引用的控制器,那么你需要使用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>

如果你选择编程来注册,你需要在应用预启动中处理.

创建一个初始化类来实现集合扫描/载入同时使用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依赖解析器 Using the Current 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 所以我们抛出了一个如下异常:

The dependency resolver is of type ‘Some.Other.DependencyResolver’ but was expected to be of type ‘Autofac.Integration.Mvc.AutofacDependencyResolver’. It also does not appear to be wrapped using DynamicProxy from the Castle Project. This issue could be the result of a change in the DynamicProxy implementation or the use of a different proxy library to wrap the dependency resolver.

最典型的地方是当我们通过 ContainerBuilder.RegisterFilterProvider() 使用行为筛选提供器(action filter provider). 筛选器提供者需要访问依赖解析器 同时能够使用 AutofacDependencyResolver.Current 来实现.

如果你看到这些,这意味着你正在用某种不能被折叠的方式修改(或者直译为装饰?)解析器,依赖于 AutofacDependencyResolver.Current 的功能将会失败. 当前的解决方案不会修改/装饰?解析器.

单元测试 Unit Testing

当对一个使用了 InstancePerRequest 组件的ASP.NET MVC 应用进行单元测试时, 你在尝试解析它的实例时将会抛出一个异常.这是因为在单元测试时没有HTTP请求。

每次请求生命周期域(per-request lifetime scope )这篇主题文章概述了对 per-request-scope 组件测试的策略.

示例实现 Example Implementation

Autofac源码中包含了一个示例web应用程序,叫做Remember.Web。它演示了各种使用Autofac对MVC的注入方式。

项目地址:https://github.com/autofac/Autofac

.NET手记-为ASP.NET MVC程序集成Autofac的更多相关文章

  1. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

  2. 如何在 ASP.NET MVC 中集成 AngularJS(2)

    在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...

  3. 如何在 ASP.NET MVC 中集成 AngularJS(1)

    介绍 当涉及到计算机软件的开发时,我想运用所有的最新技术.例如,前端使用最新的 JavaScript 技术,服务器端使用最新的基于 REST 的 Web API 服务.另外,还有最新的数据库技术.最新 ...

  4. MVC中使用EF(1):为ASP.NET MVC程序创建Entity Framework数据模型

    为ASP.NET MVC程序创建Entity Framework数据模型 (1 of 10) By  Tom Dykstra |July 30, 2013 Translated by litdwg   ...

  5. 跟我学ASP.NET MVC之三:完整的ASP.NET MVC程序-PartyInvites

    摘要: 在这篇文章中,我将在一个例子中实际地展示MVC. 场景 假设一个朋友决定举办一个新年晚会,她邀请我创建一个用来邀请朋友参加晚会的WEB程序.她提出了四个注意的需求: 一个首页展示这个晚会 一个 ...

  6. 跟我学ASP.NET MVC之二:第一个ASP.NET MVC程序

    摘要: 本篇文章带你一步一步创建一个简单的ASP.NET MVC程序.  创建新ASP.NET MVC工程 点击“OK”按钮后,打开下面的窗口: 这里选择“Empty”模板以及“MVC”选项.这次不创 ...

  7. 05 入门 - 浅谈 ASP.NET MVC程序的工作原理

    目录索引:<ASP.NET MVC 5 高级编程>学习笔记 本篇内容 1. Global.asax文件 2. RouteConfig.cs文件 3. 视图命名和寻址的规则 前面创建了一个简 ...

  8. 用开源 ASP.NET MVC 程序 Bonobo Git Server 搭建 Git 服务器(转)

    用开源 ASP.NET MVC 程序 Bonobo Git Server 搭建 Git 服务器   现在不用Git,都不好意思说自己是程序员. 当你想用Git,而源代码服务器是Windows系统时,你 ...

  9. IIS8发布Asp.net MVC程序后出现404错误,处理程序staticFile

    新部署的虚拟机,运行Asp.net MVC程序,出现如下图错误: 解决方法: 添加功能和角色->添加角色->Web服务器IIS->应用程序开发->Asp.net3.5 /Asp ...

随机推荐

  1. 简单的TSQL基础编程格式,存储过程,视图

    这里简单整理一下数据库简单的编程,变量定义,赋值,分支语句和循环(这里以Sqlserver),以及存储过程格式 首先是变量定义,赋值,分支语句 --======TSQL数据库基础编程,定义变量,赋值, ...

  2. centos系统有多个内核,修改默认启动内核

    打开系统文件 vim  /boot/grub/grub.conf default=0,意思是GRUB在默认情况下,也就是用户没有选择的情况下,去启动显示在用户界面的第一个系统:GRUB启动系统时是从0 ...

  3. 解题(GeLeiMa -生成格雷码)

    题目描述 在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同, 则称这种编码为格雷码(Gray Code),请编写一个函数,使用递归的方法生成N位的格雷码. 给定一个整数n,请返回n位的格雷码 ...

  4. 更改Oracle字符集避免乱码

    如何更改Oracle字符集避免乱码 转一位大神的笔记. 国内最常用的Oracle字符集ZHS16GBK(GBK 16-bit Simplified Chinese)能够支持繁体中文,并且按照2个字符长 ...

  5. Appium 学习二:切换Webview

    由于测试的APP是混合应用,即包含了原生代码和web网页. 混合应用在应用程序中嵌入了Webview,Webview是用来访问网页的一个控件.Webview内核也分为原生和第三方(比如腾讯X5内核) ...

  6. matlab中mat文件简单存/取

    >>abc=[,,,,,]; >>save data save file_name:命令可以将当前项目中变量的值保存到file_name中去,这里的data文件就是mat文件. ...

  7. 【转载】SQL Server - 使用 Merge 语句实现表数据之间的对比同步

    原文地址:SQL Server - 使用 Merge 语句实现表数据之间的对比同步 表数据之间的同步有很多种实现方式,比如删除然后重新 INSERT,或者写一些其它的分支条件判断再加以 INSERT ...

  8. HTTP状态码之【整理篇】

    =================================================================================== 状态码的职责:当客户端向服务器端 ...

  9. TUN/TAP编程实现

    其实关于这两种设备的编程,基本上属于八股文,大家一般都这么干. 启动设备之前 有的linux 并没有将tun 模块编译到内核之中,所以,我们要做的第一件事情就是检查我们的系统是否支持 TUN/TAP ...

  10. ABP框架系列之十五:(Caching-缓存)

    Introduction ASP.NET Boilerplate provides an abstraction for caching. It internally uses this cache ...