OWIN Katana

简介

OWIN的目标是用于解耦Web Server和Web Application。

Kantana是遵守OWIN规范的应用框架,下面四层架构也正是OWIN的规范

当应用框架与服务器都遵守OWIN时,就能做到跨平台

架构

image
Host

宿主层,是OWIN程序的载体,这个宿主可以是IIS, IIS Express, Console, Windows Service等。

Katana通过在IIS上构建一个类似适配器,使得OWIN管道能够运行在IIS上,同时Katana也已经提供了一个可以直接运行Host——OwinHost.exe

作用
1. 管理底层进程
2. 当有请求过来的时候,选择相应的Server和构建OWIN管道处理请求。

 

Server

负责绑定到 TCP 端口,监听端口发送过来的请求,同时将请求的信息依照OWIN规范,包装成字典格式,传递到下层的Middleware.
IIS既可以作为Host层,也可以作为Server层

Microsoft.Owin.Host.SystemWeb

这个是用来对应IIS的,由于IIS既是Host,又是Server. 所以这个Server实现的作用是注册ASP.NET HttpModule和HttpHandler阻断原有的处理流程,转而把请求发送到OWIN管道中处理

Microsoft.Owin.Host.HttpListener
使用HttpListener打开Socket端口,监听请求,然后将请求包装发送到OWIN管道中处理。

字典: OWIN将web应用中的request, response, session, cookie等所有相关信息都简化成下面的字典

"owin.RequestBody"

请求报文体数据流. 如果没有报文体使用Stream.Null作为占位符.

"owin.RequestHeaders"

一个 IDictionary<string, string[]><string, string[]="">  类型请求头字典. See Headers.

"owin.RequestMethod"

string containing the HTTP request method of the request (e.g., "GET""POST").

"owin.RequestPath"

string containing the request path. The path MUST be relative to the "root" of the application delegate; see Paths.

"owin.RequestPathBase"

string containing the portion of the request path corresponding to the "root" of the application delegate; see Paths.

"owin.RequestProtocol"

string containing the protocol name and version (e.g. "HTTP/1.0" or "HTTP/1.1").

"owin.RequestQueryString"

string containing the query string component of the HTTP request URI, without the leading “?” (e.g., "foo=bar&baz=quux"). The value may be an empty string.

"owin.RequestScheme"

string containing the URI scheme used for the request (e.g., "http""https"); see URI Scheme.

 

Middleware

类似Asp.Net的Module的职责,OWIN 管道中的组件,Katana提供了一个OwinMiddleware基类更加方便我们继承来实现OWIN Middleware.

 

Application

应用程序代码

 

 

Owin核心定义

 

OWIN将web应用中的request, response, session, cookie等所有相关信息都简化成字典(表见上)

这是所有运行在OWIN协议下的组件都需要遵循的接口Func<IDictionary<string, object>, Task>;​

 

 

简单的Web Host Demo

 

上面提到了Kantana支持多种宿主,这里只介绍Web Host

根据Owin协议,Middleware需要通过Func<IDictionary<string, object>, Task>添加

 

在空的MVC5项目中右键添加项可以创建一个Owin Startup类

[assembly: OwinStartup(typeof(OwinDemo.Startup))]
namespace OwinDemo
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
            app.Run(context =>
            {
                context.Response.ContentType = "text/plain";
                return context.Response.WriteAsync("Hello, world.");
            });
        }
    }
}

Startup类可以理解为传统的Global.asax

上面代码演示了注册一个Middleware到Owin管道,app.Run的方法签名如下

public static void Run(this IAppBuilder app, Func<IOwinContext, Task> handler);

这是个扩展方法,它有一个委托参数,正是Owin定义要求的那个委托,利用他我们能给管道注册Middleware

而委托参数是一个IOwinContext接口,他的成员如下

public interface IOwinContext
{
    IAuthenticationManager Authentication { get; }
    IDictionary<string, object> Environment { get; }
    IOwinRequest Request { get; }
    IOwinResponse Response { get; }
	TextWriter TraceOutput { get; set; }
    T Get<T>(string key);
    IOwinContext Set<T>(string key, T value);
}

可以看到Http请求中要用到的东西都能通过这个接口获得.另外这次请求相关的数据都封装成字典保存在Environment

 

 

上述代码中的[assembly: OwinStartup(typeof(OwinDemo.Startup))]是用来设置Owin启动类

更多的设置方法看下文

 

Middleware

 

我们通过集成OwinMiddleware来编写自己的中间件

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

中间件的执行过程根据Startup类中注册的顺序.上述代码的Next.Invoke代表执行下一个中间件

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use((x, next) =>
        {
            x.Response.ContentType = "text/html";
            return next.Invoke();
        });
        app.Use((x, next) =>
        {
            x.Response.WriteAsync("1 Before");
            next.Invoke();
            return x.Response.WriteAsync("1 After");
        });
        app.Use((x, next) =>
        {
            x.Response.WriteAsync("2 Before");
            next.Invoke();
            return x.Response.WriteAsync("2 After");
        });
        app.Run(x => x.Response.WriteAsync("<br/>hello world<br/>"));
    }
}

 注意app.Use是添加中间件,而app.Run仅仅只是执行,app.Run后面的代码是不执行的,也就是在app.Run后面使用app.Use是无效的

 

Owin启动

 

一.约定

Kantana寻找一个名字程序集名称或全局命名空间匹配的命名空间中的 Startup

 

二.OwinStartup 特性

在类名上面添加

[assembly: OwinStartup(typeof(startClassType))]​

 

三.使用配置文件

在web.config中的appSetting添加相关配置

指定类名

<add key="owin:appStartup" value="StartupDemo.ProductionStartup" />​

指定类名和程序集

<add key="owin:appStartup" value="StartupDemo.ProductionStartup, StartupDemo" />​

带friendlyname的配置方式

<add key="owin:appStartup" value="ProductionConfiguration" />   ​

这种方式要求类名上面也要使用特性标签,并注明friendlyname

[assembly: OwinStartup("ProductionConfiguration", typeof(StartupDemo.ProductionStartup2))]​

 

 

 

摘抄至

http://www.asp.net/aspnet/overview/owin-and-katana

http://www.cnblogs.com/JustRun1983/p/3967757.html

http://www.cnblogs.com/neverc/p/4864414.html


Owin ServerHost


相信大部分人都是在传统Asp.Net应用上集成Owin,那么Owin又是如何取代Asp.Net管道的作用?





 

comments powered by Disqus