Currently, in the both the Web API and MVC frameworks, dependency injection support does not come into play until after the OWIN pipeline has started executing. This is simply a result of the OWIN support being added to both frameworks after their initial release. In fact, the OWIN support in MVC does not yet extend to the self hosting scenario and is limited to plugging in OWIN middleware.

I had two primary objectives when creating these new OWIN packages for Autofac:

  • Extend the Autofac lifetime scope from the OWIN pipeline into the MVC and Web API integrations
  • Make dependency injection avaialable to OWIN middleware components

Due to the somewhat fragmented nature of the DI support in the ASP.NET stack, achieving this goal required a bit of trickery and black magic. For that reason the packages are currently pre-release and marked as alpha. Hopefully you can pull them from NuGet and help test them out.

Enabling DI for OWIN middleware

Lets start with a service interface for a logging dependency...

public interface ILogger
{
void Write(string message, params object[] args);
}

...along with its rather unimaginative implementation (just imagine something more interesting).

public class Logger : ILogger
{
public void Write(string message, params object[] args)
{
Debug.WriteLine(message, args);
}
}

To enable dependency injection for OWIN middleware derive from OwinMiddleware as usual, and add any additional constructor dependencies after the constructor parameter for the next middleware in the chain. In the example below we are adding the ILogger dependency to the middleware.

public class LoggerMiddleware : OwinMiddleware
{
private readonly ILogger _logger; public LoggerMiddleware(OwinMiddleware next, ILogger logger) : base(next)
{
_logger = logger;
} public override async Task Invoke(IOwinContext context)
{
_logger.Write("Inside the 'Invoke' method of the 'LoggerMiddleware' middleware."); foreach (var pair in context.Environment)
_logger.Write("Key: {0}, Value: {1}", pair.Key, pair.Value); await Next.Invoke(context);
}
}

To wire this up we have to register the middleware and its dependencies with the container, and then enable the middleware dependency injection support via a call to UseAutofacMiddleware. This call should be the first piece of middleware registered with the IAppBuilder.

var builder = new ContainerBuilder();

builder.RegisterType<LoggerMiddleware>().InstancePerApiRequest();
builder.Register(c => new Logger()).As<ILogger>().InstancePerLifetimeScope(); app.UseAutofacMiddleware(container);

This particular extension method is included in the Autofac.Owin package which is shared by the Autofac.WebApi2.Owin and Autofac.Mvc5.Owin packages. You would not normally use this package by itself because of the second role the shared package plays. Not only is it responsible for adding middleware dependency injection support, it also creates an Autofac ILifetimeScope instance for each request early in the OWIN pipeline. You can access this lifetime scope using the GetAutofacLifetimeScope method on IOwinContext. The OWIN packages for the Web API and MVC integrations use this method to access the lifetime scope and make it available further along in the request.

Extending the lifetime scope to Web API

To enable the lifetime scope created during the OWIN request to extend into the Web API dependency scope call the UseAutofacWebApi method.

app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(GlobalConfiguration.Configuration);

This will add a DelegatingHandler which extracts the ILifetimeScope from the IOwinContext. Once it has a hold of the ILifetimeScope an AutofacWebApiDependencyScope is created and added into the appropriate HttpRequestMessage property that Web API expects the IDependencyScope to be available from. The code below shows this task being performed during the SendAsync method of the handler.

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null) throw new ArgumentNullException("request"); var owinContext = request.GetOwinContext();
if (owinContext == null) return base.SendAsync(request, cancellationToken); var lifetimeScope = owinContext.GetAutofacLifetimeScope();
if (lifetimeScope == null) return base.SendAsync(request, cancellationToken); var dependencyScope = new AutofacWebApiDependencyScope(lifetimeScope);
request.Properties[HttpPropertyKeys.DependencyScope] = dependencyScope; return base.SendAsync(request, cancellationToken);
}

Notice that we still made a call to UseAutofacMiddleware. This is required because along with enabling the middleware DI support, this is also responsible for placing the lifetime scope in the OWIN context. I'm not totally happy with this dual responsibility but it does reduce the API surface area and means less IAppBuilder extensions are required. For now, if you don't want to use middleware DI support, don't register your middleware with the container.

Extending the lifetime scope to MVC

To enable the lifetime scope created during the OWIN request to extend into the MVC request call the UseAutofacMvc method on your IAppBuilder instance.

app.UseAutofacMiddleware(container);
app.UseAutofacMvc();

Just like with Web API we need to ensure that UseAutofacMiddleware has been called first. You only need to call this method once, even when using both the MVC and Web API integrations together. Remember, the call to UseAutofacMiddleware should be made as early as possible during the bootstrapping process.

In the MVC middleware we are also retrieving the ILifetimeScope from the IOwinContext, but in this case we are placing it in the HttpContext as is expected by the MVC integration. The code below shows this process directly implemented in a middleware method.

public static IAppBuilder UseAutofacMvc(this IAppBuilder app)
{
return app.Use(async (context, next) =>
{
var lifetimeScope = context.GetAutofacLifetimeScope();
var httpContext = CurrentHttpContext(); if (lifetimeScope != null && httpContext != null)
httpContext.Items[typeof(ILifetimeScope)] = lifetimeScope; await next();
});
}

In case you are wondering, CurrentHttpContext is an internal property that returns a HttpContextBase allowing for mocking of the HTTP context during unit testing.

NuGet Packages

As mentioned earlier the packages are currently pre-release, so don't forget the -Preswitch on the command line, or the Include Prerelease option in the GUI. Please report any issues that you find on GitHub.

Autofac Web API OWIN Integration:

Install-Package Autofac.WebApi2.Owin -Pre

Autofac MVC 5 OWIN Integration:

Install-Package Autofac.Mvc5.Owin -Pre

Please note that you still need to configure the relevant dependency resolver for each integration: AutofacWebApiDependencyResolver for Web API, and AutofacDependencyResolverfor MVC.

OWIN support for the Web API 2 and MVC 5 integrations in Autofac的更多相关文章

  1. 使用 OWIN 作为 ASP.NET Web API 的宿主

    使用 OWIN 作为 ASP.NET Web API 的宿主 ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动 设备)的 HTTP 服务. ASP.NET ...

  2. 使用 OWIN Self-Host ASP.NET Web API 2

    Open Web Interface for .NET (OWIN)在Web服务器和Web应用程序之间建立一个抽象层.OWIN将网页应用程序从网页服务器分离出来,然后将应用程序托管于OWIN的程序而离 ...

  3. ASP.NET Web API - ASP.NET MVC 4 系列

           Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...

  4. web api .net C# mvc API返回XML文档的解析并取值

    [HttpGet] public System.Net.Http.HttpResponseMessage GetNotify() { var xmlstring = @" <xml&g ...

  5. 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP. ...

  6. Use OWIN to Self-Host ASP.NET Web API 2

      Open Web Interface for .NET (OWIN)在Web服务器和Web应用程序之间建立一个抽象层.OWIN将网页应用程序从网页服务器分离出来,然后将应用程序托管于OWIN的程序 ...

  7. CORS support for ASP.NET Web API (转载)

    CORS support for ASP.NET Web API Overview Cross-origin resource sharing (CORS) is a standard that al ...

  8. Asp.Net Web API VS Asp.Net MVC

    http://www.dotnet-tricks.com/Tutorial/webapi/Y95G050413-Difference-between-ASP.NET-MVC-and-ASP.NET-W ...

  9. 关于 Web Api 2 认证与授权

    认证与授权 认证与授权,Authentication and Authorize,这个是两个不同的事.认证是对访问身份进行确认,如验证用户名和密码,而授权是在认证之后,判断是否具有权限进行某操作,如 ...

随机推荐

  1. 通过javascript在网页端解压zip文件并查看压缩包内容

    WEB前端解压ZIP压缩包 web前端解压zip文件有什么用: 只考虑标准浏览器的话, 服务器只要传输压缩包到客户端, 节约了带宽, 而且节约了传输时间, 听起来好像很厉害的说:     如果前端的代 ...

  2. 强连通 HDU 1827

    n个点m条边 n个权lcy 要叫这个人的花费 m条边 缩点后 新的图中 入度为0的点要通知  通知强连通分量中权值最小的 #include<stdio.h> #include<alg ...

  3. Mysql-windows下修改密码

    忘记密码修改(以下各种方法视情况而使用,本人测试,有些都是案情况才可行,但都是有设置成功过) 注:修改密码成功后一定要记得刷新下权限(否则将导致不能使用当前用户连接) mysql>FLUSH P ...

  4. Android中图像变换Matrix的原理、代码验证和应用(一)

    第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...

  5. 【CodeForces 699D】Fix a Tree

    dfs找出联通块个数cnt,当形成环时,令指向已访问过节点的节点变成指向-1,即做一个标记.把它作为该联通图的根. 把所有联通的图变成一颗树,如果存在指向自己的点,那么它所在的联通块就是一个树(n-1 ...

  6. mysql字段冲突报错

    check the manual that corresponds to your MySQL server version for the right syntax to use near 出现这个 ...

  7. 图像卷积、相关以及在MATLAB中的操作

    图像卷积.相关以及在MATLAB中的操作 2016年7月11日 20:34:35, By ChrisZZ 区分卷积和相关 图像处理中常常需要用一个滤波器做空间滤波操作.空间滤波操作有时候也被叫做卷积滤 ...

  8. NOI题库刷题日志 (贪心篇题解)

    这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制:  1000ms  内存限制:  65536kB 描述 在一个平面上,如果有两个点( ...

  9. asp.net接收ajax请求参数时为空的现象

    如题,如果使用ajax请求asp.net后台时,如果使用jquery时,默认是添加了请求头,使后台能识别,并能通过Request对象进行获取. 但是如果你使用的是window.XMLHttpReque ...

  10. CSS中的a标签几个访问状态记录

    a:link {color: #FF0000}     /* 未访问的链接 */a:visited {color: #00FF00}  /* 已访问的链接 */a:hover {color: #FF0 ...