Middleware是OWIN管道的基本组成单元,最后拼接的OWIN管道来处理客户端请求,输出网页。这篇文章,首先看看Web Form, MVC, Web API如何结合OWIN使用。 然后将如何编写Middleware和编写一个具体的Cache Middleware.

阅读目录:

一. 原有的Web Form, MVC项目如何结合OWIN?

1.1 通过路由配置,将程序分成多个部分,一些部分由Asp.net Web Form或者MVC处理,另外一部分由OWIN管道处理。
     1.2 在Web Form, MVC之前插入OWIN

二. Web API以Middleware注册到OWIN管道

三. 自定义Cache Middleware

3.1 HelloWorld Middleware
     3.2 Cache Middleware

四,总结

一,原有的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系统上运行。

那么在当前的情况下,OWIN和Web Form, MVC的结合开发一般是两种形式:

1. 通过路由配置,将程序分成多个部分,一些部分由Asp.net Web Form或者MVC处理,另外一部分由OWIN管道处理。

// 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();
} //添加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; }//确定缓存的时间
}
}

接下来,我们要改造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());
} context.Response.Write(response);
return Task.FromResult();
}
}

最后,将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统一到一个大的平台下,这将更加有助于混合编程。

下一代Asp.net开发规范OWIN(3)—— Middleware的更多相关文章

  1. 下一代Asp.net开发规范OWIN(1)—— OWIN产生的背景以及简单介绍

    随着VS2013的发布,微软在Asp.Net中引入了很多新的特性,比如使用新的权限验证模块Identity, 使用Async来提高Web服务器的吞吐量和效率等.其中一个不得不提的是OWIN和Katan ...

  2. <转>下一代Asp.net开发规范OWIN(1)—— OWIN产生的背景以及简单介绍

    2014-09-04 07:22 by JustRun http://www.cnblogs.com/JustRun1983/p/3955238.html 随着VS2013的发布,微软在Asp.Net ...

  3. 下一代Asp.net开发规范OWIN(2)—— Katana介绍以及使用

    接上篇OWIN产生的背景以及简单介绍,在了解了OWIN规范的来龙去脉后,接下来看一下Katana这个OWIN规范的实现,并看看如何使用在我们的Web开发中. 阅读目录: 一. Katana项目的结构和 ...

  4. [ASP.NET] 下一代ASP.NET开发规范:OWIN

    今天投简历 准备面试了... 本节目录: OWIN简介 OWIN规范 Katana Hello World(3种Host) 自定义Middleware OWIN简介 OWIN(Open Web Int ...

  5. ASP.NET开发规范:OWIN

    ASP.NET开发规范:OWIN 今天投简历 准备面试了... 本节目录: OWIN简介 OWIN规范 Katana Hello World(3种Host) 自定义Middleware OWIN简介 ...

  6. ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上

    一.前言 大家都知道,在之前,我们Asp.net 的网站都只能部署在IIS上,并且IIS也只存在于Windows上,这样Asp.net开发的网站就难以做到跨平台.由于微软的各项技术的开源,所以微软自然 ...

  7. C#开发规范总结(个人建议)

    .NET开发编程规范 章程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的" ...

  8. 转载 C#中敏捷开发规范

    转载原地址 http://www.cnblogs.com/weixing/archive/2012/03/05/2380492.html 1.命名规则和风格 Naming Conventions an ...

  9. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

随机推荐

  1. EntityFramework 外键值映射

    如果在 EF OnModelCreating 中配置了实体外键映射,也就是 SQL Server 中的 ForeignKey,那么我们在添加实体的时候,主实体的主键值会自动映射到子实体的外键值,并且这 ...

  2. Google和Baidu常用的搜索技巧--转

    原文链接:http://mp.weixin.qq.com/s?__biz=MjM5NTY0MTY1OQ==&mid=2654509772&idx=1&sn=754454e374 ...

  3. objective-c 语法快速过(3)

    oc 里的匿名对象 oc 这里,很少用到,因为并不适用于oc的内存管理,只是面试笔试也许出现,要求能看懂,不要在项目里这样写,因为写匿名对象,会造成内存泄露 #import <Foundatio ...

  4. 韩顺平_linux_随堂笔记

    这还是自己3年前(2011年)整理的笔记,记得当时那会儿自己对Linux还特别的憧憬,也很喜欢韩老师的讲课风格,边看边做笔记乐此不彼,现在开通了技术博客,所以把当年的笔记也放上来和大家分享.同时推荐没 ...

  5. 大型网站提速关键技术(页面静态化,memcached,MySql优化)(二)

    一:页面静态化 几个概念: 静态网址:(比如:http://localhost/abc.html) 特点:1.利用seo(search engine optimization) 搜索引擎优化;2:访问 ...

  6. 《Head First 设计模式》之装饰者模式

    作者:Grey 原文地址:http://www.cnblogs.com/greyzeng/p/5922248.html 模式名称 装饰者模式(Decorator Pattern) 需求 定义咖啡厅中的 ...

  7. WinForm 代码实现以管理员身份运行

    [STAThread] static void Main(string[] Args) { //获得当前登录的Windows用户标示 System.Security.Principal.Windows ...

  8. 【C#】分享一个弹出容器层,像右键菜单那样召即来挥则去

    适用于:.net2.0+ Winform项目 ------------------201508261813更新(源码有更新.Demo未更新)------------------ 重新绘制调整大小手柄( ...

  9. 【C#进阶系列】30 学习总结

    前面学起来还是很顺的,毕竟很多都接触过. 后面学起来只能用“磨”来形容,以至于八章用了2个月.(当然也有相当一些原因是这两个月中发生了一些个人生活上的问题) 总的来说收获超大,这种感觉就像大一的时候学 ...

  10. WCF入门教程1——WCF简要介绍

    什么是WCF Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台. 整合了原有的windo ...