Katana介绍以及使用 一. Katana项目的结构和包含的内容 二. Katana示例代码Hello World 三. OWIN Startup配置类详解

Katana介绍以及使用

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

阅读目录:

一. Katana项目的结构和包含的内容

     1.1 Host
     1.2 Server
     1.3 Middleware
     1.4 Application

二. Katana示例代码Hello World

     2.1 使用IIS Host运行Hello World
   2.2 将Hello World迁移到在自定义Host

三. OWIN Startup配置类详解

     3.1 怎么没有OWIN规范中的IDictionary<string, object>和Func<IDictionary<string, object>, Task>?
     3.2 Host是如何链接到Startup类的?

通过了解Katana项目结构,我们能够更加深入的理解OWIN规范。下面这张图就是Katana项目的主要架构。

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

上图中的各个部分解释:

1.1 Host

宿主只是一个进程,是整个OWIN程序的载体。这个宿主可以是IIS, IIS Express, Console, Windows Service等。
Host的主要作用:
1. 管理底层进程
2. 当有请求过来的时候,选择相应的Server和构建OWIN管道处理请求。

我们最熟悉的Host就是IIS/Asp.net.  不过IIS既是Host, 也是Server. 在IIS中使用标准的HttpModule和HttpHandler类型来响应请求。Katana通过在IIS上构建一个类似适配器,使得OWIN管道能够运行在IIS上。
我们还可以自己实现一个简单的Host, 这个Host可以在Console中,也可以是一个Windows Service进程。同时Katana也已经提供了一个可以直接运行Host——OwinHost.exe

1.2 Server

负责绑定到 TCP 端口,监听端口发送过来的请求,同时将请求的信息依照OWIN规范,包装成字典格式,传递到下层的Middleware.
Katana项目包含了2个Server实现:
Microsoft.Owin.Host.SystemWeb
这个是用来对应IIS的,由于IIS既是Host,又是Server. 所以这个Server实现的作用是注册ASP.NET HttpModule和HttpHandler阻断原有的处理流程,转而把请求发送到OWIN管道中处理。
Microsoft.AspNet.Host.SystemWeb依赖于Sysetm.Web, 和IIS耦合厉害,所以无法迁移到非IIS服务器

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

1.3 Middleware:

这是为组成 OWIN 管道中的组件。 它可以是从简单压缩组件到 ASP.NET Web API 这样的完整框架.
当从客户端发送一个请求,这个请求就会传到OWIN管道中处理。这个管道是在startup code中初始化的。组成管道的组件就是Middleware.
要遵循OWIN标准,Middleware应该要实现

Func<IDictionary<string, object>, Task>

Katana提供了一个OwinMiddleware基类更加方便我们继承来实现OWIN Middleware.

1.4 Application

这是您的程序代码。 由于 Katana 并不取代 ASP.NET,而是一种编写和托管组件的新方式,因此现有的 ASP.NET Web API 和 SignalR 应用程序将保持不变,因为这些框架可以参与 OWIN 管道。 事实上,对于这些类型的应用程序,Katana 组件只需使用一个小的配置类即可见。
OWIN和Katana并不是一个全新的开发方式,并不取代 ASP.NET,是实现Host, Server和Applicantion之间解耦,是一种编写和托管组件的新方式 。比如使用OWIN方式开发Web API, 我们仍然还是使用Asp.net Web API. 只是Web API变成了我们OWIN管道的一个组成部分了。正常开发中,我们感觉不到OWIN的存在,只是在startup代码中,构建我们的OWIN管道。通常,对于Web API和SignalR这种大型组件,我们都是注册在OWIN管道的最后。但是像authentication , cache这样的组件,我们通常会注册到管道前部。

二. Katana示例代码Hello World

下面的示例是在VS 2013中操作的。

2.1 使用IIS Host运行Hello World

使用IIS作为宿主,是我们常用的方式。通过在IIS上建立一个OWIN管道,运行我们的程序。
首先,在VS2013中,创建一个新的Asp.net程序。

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

在弹出框中,选择Empty模板

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

从Nuget中添加支持包

下一步是添加OWIN的支持包。从Tools-> Library Package Manager-> Package Manager Console. 然后在命令窗口中,运行install-package Microsoft.Owin.Host.SystemWeb.
也可以直接在nuget包管理界面上添加

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

添加Startup启动类
Startup类的作用是用来初始化OWIN管道,这里,我们添加和初始化OWIN管道中的Middleware.

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

在Startup1.Configuration方法中,添加如下代码:

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解
public void Configuration(IAppBuilder app)
{
    // New code:
    app.Run(context =>
    {
        context.Response.ContentType = "text/plain";
        return context.Response.WriteAsync("Hello, world.");
    });
}
Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

上面的代码做的事情,就是把一个简单的Middleware注册到OWIN管道中。这个中间件完成的事情非常简单: 当接受到请求的时候,输出Hello World.
启动程序运行,结果页面如下:

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

2.2 将Hello World迁移到在自定义Host

从IIS Host迁移到自定义Host非常简单。使用IIS Host, IIS同时充当了Host和Server的角色。在自定义Host中, 我们将用Console程序作为Host, 同时用HttpListener类来作为Server,监听固定端口发送的Http请求.
首先创建一个简单的Console应用程序,用Nuget添加Microsoft.Owin.SelfHost

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

同样添加上我们的Startup1.cs, 然后将我们的Console程序改造成Host宿主。

Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解
class Program
{
    static void Main(string[] args)
    {
        using (Microsoft.Owin.Hosting.WebApp.Start<Startup1>("http://localhost:9000"))
        {
            Console.WriteLine("Press [enter] to quit...");
            Console.ReadLine();
        }
    }
}
Katana介绍以及使用
一. Katana项目的结构和包含的内容
二. Katana示例代码Hello World
三. OWIN Startup配置类详解

启动程序,然后在浏览器中键入http://localhost:9000访问.
可以看到,OWIN的应用,耦合关联非常少,非常容易地在不同的Host之间迁移。以后在有除IIS外更多优秀的Host/Server涌现的时候,我们的选择就会更多

三. OWIN Startup配置类详解

上面我们分别用IIS和Console为宿主,运行了一个简单的Hello World程序。虽然只是一个简单的Hello World, 其实里面包含的内容还是挺多的,下面就来一一介绍。

3.1 怎么没有OWIN规范中的IDictionary<string, object>和Func<IDictionary<string, object>, Task>?

上篇文章中,讲到OWIN规范的时候,提到过在OWIN管道中传输的数据形式是IDictionary<string, object>,但是在我们的代码中,并没有出现.

原因是在微软的OWIN实现中,将字典类型包装到了IOwinContext接口类型中。其实可以通过属性Environment可以访问到该字典,同时还包装常用的request, reponse属性。这样我们就无需直接和IDictionary<string, object>打交道, 在OWIN规范上,字典类型是个非常好的设计,简单通用,但是在实际开发中,直接操作字典类型获取object, 然后再转换类型等毕竟不是一个直观和方便的过程。

我们的Startup.cs代码中,下面的context参数类型,其实就是IOwinContext.

app.Run(context => 
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync("Hello, world.");
});

关于另外一个问题,Func<IDictionary<string, object>, Task>在哪里?我们来看看Run函数的定义就一目了然了:

public static void Run(this IAppBuilder app, Func<Microsoft.Owin.IOwinContext, System.Threading.Tasks.Task> handler);

Startup.cs中,主要完成的工作,就是使用IAppBuilder来注册Middleware到OWIN管道中。我们用lambda表达式注册的Hello World, 其实就是一个Middleware组件,只是这个Middleware组件太简单了。

3.2 Host是如何链接到Startup类的?

无论你使用IIS, IIS Express还是OWIN Host, 微软在这些Host上实现的Service都会依照特定的规则来寻找到Startup类,执行Configuration方法,注册Middleware.

默认名称匹配
可以定义Startup.cs类,只要这个类的namespace和Assembly的名称相同。那么,这个Startup.cs中的Configuration方法,就会在OWIN管道初始化的时候执行。

使用OwinStartup Attribute
这就是我们例子中使用的方式,直接指定哪个具体类是Startup类。

在配置文件的appSetting 节点设置

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

通过上面的讲解,希望能帮助大家理解Katana在实际项目中的使用。
下一篇中,更加接近实战,一起看看我们编写Middleware

阅读目录:

一. Katana项目的结构和包含的内容

     1.1 Host
     1.2 Server
     1.3 Middleware
     1.4 Application

二. Katana示例代码Hello World

     2.1 使用IIS Host运行Hello World
   2.2 将Hello World迁移到在自定义Host

三. OWIN Startup配置类详解

     3.1 怎么没有OWIN规范中的IDictionary<string, object>和Func<IDictionary<string, object>, Task>?
     3.2 Host是如何链接到Startup类的?