Middleware是OWIN管道的基本组成单元,最后拼接的OWIN管道来处理客户端请求,输出网页。这篇文章,首先看看Web Form, MVC, Web API如何结合OWIN使用。 而后将如何编写Middleware和编写一个具体的Cache Middleware.web
阅读目录:编程
一. 原有的Web Form, MVC项目如何结合OWIN?api
1.1 经过路由配置,将程序分红多个部分,一些部分由Asp.net Web Form或者MVC处理,另一部分由OWIN管道处理。
1.2 在Web Form, MVC以前插入OWIN缓存
二. Web API以Middleware注册到OWIN管道
三. 自定义Cache Middlewareapp
3.1 HelloWorld Middleware
3.2 Cache Middlewareide
四,总结函数
一,原有的Web Form, MVC项目如何结合OWIN?
坏消息,很是抱歉,尽管OWIN是革命性的,可是Web Form和MVC如今还不能做为一个中间件集成到OWIN管道中。缘由在第一篇中Asp.net的历史中有分析过,缘由就是Web Form和MVC依赖于System.Web.dll中的不少类型。而在OWIN管道中,是没法提供这些依赖的。不过好消息是,在Asp.net vNext中,将会完全告别System.Web.dll依赖, 那个时候,Asp.net vNext将是集大成者。据说vNext项目组正在和Mono团队一块儿工做,使得Asp.net vNext开发的项目可以在*nix, osx系统上运行。post
那么在当前的状况下,OWIN和Web Form, MVC的结合开发通常是两种形式:ui
1. 经过路由配置,将程序分红多个部分,一些部分由Asp.net Web Form或者MVC处理,另一部分由OWIN管道处理。spa
// How to hook OWIN pipelines into the normal Asp.Net route table side by side with other components.
protected void Application_Start(object sender, EventArgs e)
{
//owin开头的访问路径将会发送到startup.cs初始化的OWIN管道处理
RouteTable.Routes.MapOwinPath("/owin");
//special开头的访问路径将会由OwinApp2管道来处理
RouteTable.Routes.MapOwinPath("/special", app =>
{
app.Run(OwinApp2.Invoke);
});
}
如上面代码,在Application_Start函数或者路由配置函数中,分别为/owin路径和/special配置了不一样的OWIN管道。
完整的代码,请移步这里http://aspnet.codeplex.com/sourcecontrol/latest#Samples/Katana/AspNetRoutes/Global.asax.cs
2. 在Web Form, MVC以前插入OWIN
在Web Form和MVC项目中,也能够添加Startup.cs, 指定成为OWIN的初始化类型,那么请求会先通过OWIN管道处理,最后转向Web Form或者MVC程序。这种方式,经常用来配置log, authentication, cache等等这些Middleware.
二,Web API以Middleware注册到OWIN管道
Web API因为无任何依赖于System.web.dll, 因此Web API能够做为Middleware注册到OWIN管道中。
具体方法以下:
public class Startup
{
// Invoked once at startup to configure your application.
public void Configuration(IAppBuilder builder)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute("Default", "api/{controller}/{customerID}", new { controller = "Customer", customerID = RouteParameter.Optional });//定义web api route
//xml格式输出结果
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.Remove(config.Formatters.JsonFormatter);
// config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;
//将web api以Middleware注册到OWIN管道中
builder.UseWebApi(config);
}
}
三,自定义Cache Middleware
3.1 HelloWorld Middleware
先建一个Middleware, 经过继承OwinMiddleware基类。这个Middleware的功能很是简单,就是打印当前的系统时间。
public class HelloWorldMiddleware : OwinMiddleware
{
public HelloWorldMiddleware(OwinMiddleware next) : base(next)
{
}
public override Task Invoke(IOwinContext context)
{
var response = "Hello World! It is " + DateTime.Now;
context.Response.Write(response);
return Next.Invoke(context);
}
}
将该Middleware注册到OWIN管道后,执行获得的网页:

只要咱们不断的刷新网页,每次显示的时间都会不一样,由于每次都会从新读取系统时间,从新呈现页面。
3.2 Cache Middleware
实现cache middleware的思路比较简单,以访问的Url为key, 以输出的内容为value。第一次访问的时候,会缓存下来输出的内容,在下次访问的时候,将直接返回缓存的内容,而不是从新生成。具体代码以下:
public class CacheMiddleware : OwinMiddleware
{
private readonly IDictionary<string, CacheItem> _responseCache = new Dictionary<string, CacheItem>(); //Cache存储的字典
public CacheMiddleware(OwinMiddleware next)
: base(next)
{
}
public override Task Invoke(IOwinContext context)
{
context.Environment["caching.addToCache"] = new Action<IOwinContext, string, TimeSpan>(AddToCache);
var path = context.Request.Path.Value;
//若是访问的路径没有缓存,就传递到OWIN管道的下一层中处理
if (!_responseCache.ContainsKey(path)) {
return Next.Invoke(context);
}
var cacheItem = _responseCache[path];
//检查缓存是否到期
if (cacheItem.ExpiryTime <= DateTime.Now)
{
_responseCache.Remove(path);
return Next.Invoke(context);
}
//直接从缓存中输出,而不是从新render页面
context.Response.Write(cacheItem.Response);
return Task.FromResult(0);
}
//添加cache的方法,将会以委托的方式存放到OWIN管道字典中,这样任何OWIN的Middleware都可以调用,从而保存数据到缓存
public void AddToCache(IOwinContext context, string response, TimeSpan cacheDuration)
{
_responseCache[context.Request.Path.Value] = new CacheItem { Response = response, ExpiryTime = DateTime.Now + cacheDuration };
}
private class CacheItem
{
public string Response { get; set; }//保存缓存的内容
public DateTime ExpiryTime { get; set; }//肯定缓存的时间
}
}
View Code
接下来,咱们要改造HelloWorldMiddleware, 在HelloWorldMiddleware输出后,咱们把输出的内容保存到Cache中。具体代码以下:
public class HelloWorldMiddleware : OwinMiddleware
{
public HelloWorldMiddleware(OwinMiddleware next) : base(next)
{
}
public override Task Invoke(IOwinContext context)
{
var response = "Hello World! It is " + DateTime.Now;
if (context.Environment.ContainsKey("caching.addToCache"))//这里直接从OWIN管道的字典中,检查是否有add cache, 若是存在,就将输出内容缓存到cache中,过时时间为10分钟。
{
var addToCache = (Action<IOwinContext, string, TimeSpan>)context.Environment["caching.addToCache"];
addToCache(context, response, TimeSpan.FromMinutes(10));
}
context.Response.Write(response);
return Task.FromResult(0);
}
}
View Code
最后,将CacheMiddleware添加到OWIN管道中发挥做用,注意注册管道的顺序问题,Middleware是必定要在HelloWorldMiddleware以前的。
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<CacheMiddleware>();
app.Use<HelloWorldMiddleware>();
}
}
四,总结
经过上面的示例,但愿对你们如何编写Middleware有些基本的概念。
OWIN的优点在上面的例子中应该有些体现,就是Middleware之间经过数据和行为规范, 你们能够一块儿无缝地协同工做,任何第三方的Middleware均可以很是简单的集成到OWIN管道中,这应该是OWIN最大的魅力所在,开放的魅力。
同时, OWIN的目标是将Web Form, MVC, Web API统一到一个大的平台下,这将更加有助于混合编程。