https://msdn.microsoft.com/zh-cn/magazine/dn451439.aspx(Katana 项目入门)

一不小心写了个WEB服务器

快刀斩乱麻之 Katana

OWIN知识

OWIN的全称是Open Web Interface For .Net。

OWIN提供的只是一种规范,而没有具体实现。其目的是在web服务器和应用程序组件之间隔离出一个抽象层,使它们之间解耦。

应用程序委托和环境字典

OWIN将服务器与应用程序之间的交互减少到一小部分类型和单个函数签名,这个函数签名被称为应用程序委托(即 AppFunc):

using AppFunc = Func<IDictionary<string, object>, Task>;

基于 OWIN 的应用程序中的每个组件都向服务器提供应用程序委托。 然后,这些组件链接成一个管道,基于 OWIN 的服务器将会向该管道推送请求。

一个符合OWIN的web服务器,需要将请求信息(应用程序状态、请求状态和服务器状态等所有相关信息)包装到一个字典里(应用程序委托上指定的 IDictionary<string, object>,这种数据结构称为环境字典),从而使得许多不同的框架和组件作者可以在一个 OWIN 管道中进行互操作,而不必强制实施对特定 .NET 对象模型的协议。

虽然任何键/值数据都可以插入到环境字典中,但 OWIN 规范为某些 HTTP 核心元素定义了键: 

key value
"owin.RequestBody" 一个带有请求正文(如果有)的流。如果没有请求正文,Stream.Null 可以用作占位符。
"owin.RequestHeaders" 请求标头的 IDictionary<string, string[]>。
"owin.RequestMethod" 一个包含请求的 HTTP 请求方法的字符串(例如 GET 和 POST)。
"owin.RequestPath" 一个包含请求路径的字符串。 此路径必须是应用程序委托的“根”的相对路径。
"owin.RequestPathBase" 一个字符串,包含对应于应用程序委托的“根”的请求路径部分。
"owin.RequestProtocol" 一个包含协议名称和版本的字符串(例如 HTTP/1.0 或 HTTP/1.1)。
"owin.RequestQueryString" 一个字符串,包含 HTTP 请求 URI 的查询字符串组成部分,不带前导“?”(例如 foo=bar&baz=quux)。 该值可以是空字符串。
"owin.RequestScheme" 一个字符串,包含用于请求的 URI 方案(例如 HTTP 或 HTTPS)。

随着请求在OWIN管道中流动,每个中间件(Middleware,集成到管道中的组件或应用程序)所要做的就是读取、修改这个字典的数据。最后,Web服务器得到这个层层处理过的字典,然后输出网页到客户端。

与ASP.NET管道相比,OWIN规范非常简洁,且并没有引用.Net Framework中的System.Web.dll。

  1. 新的组件能够非常简单的开发和应用
   2. 程序能够简便地在host和OS上迁移

Katana

Katana 项目是 Microsoft 创建和推出的基于 OWIN 的组件和框架集合。

https://katanaproject.codeplex.com

但上面这个项目最后一次提交是15年1月

目前它的托管代码已经被拆分:

New 'Katana' Source:

Katana 体系结构

  • 主机:运行应用程序的进程,可以是从 IIS 或独立可执行文件到您自己的自定义程序的任何内容。 主机负责启动、加载其他 OWIN 组件和正常关闭。
  • 服务器:负责绑定到 TCP 端口,构造环境字典和通过 OWIN 管道处理请求。
  • 中间件:这是为处理 OWIN 管道中的请求的所有组件指定的名称。 它可以是从简单压缩组件到 ASP.NET Web API 这样的完整框架,不过从服务器的角度而言,它只是一个公开应用程序委托的组件。
  • 应用程序:这是您的代码。 由于 Katana 并不取代 ASP.NET,而是一种编写和托管组件的新方式,因此现有的 ASP.NET Web API 和 SignalR 应用程序将保持不变,因为这些框架可以参与 OWIN 管道。 事实上,对于这些类型的应用程序,Katana 组件只需使用一个小的配置类即可见。

在体系结构方面,Katana 可以按其中每个层都能够轻松替代的方式分解,通常不需要重新生成代码。 在处理 HTTP 请求时,各个层一起工作,方式类似于下图中所示的数据流。

————

使用IIS做Host和Server

首先建立一个空的web应用程序。因为默认的 Katana 主机会在此 /bin 文件夹中查找程序集。而Web应用程序默认会将编译的程序集直接放在 /bin 文件夹而不是 /bin/debug 文件夹中。

删除无关文件,引入OWIN的支持包

添加Startup启动类

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

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

public class Startup
{
public void Configuration(IAppBuilder app)
{
// New code:
app.Run(context =>
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync("Hello, world."+ context.Request.Uri);
});
}
}

上面的代码做的事情,就是把一个简单的Middleware注册到OWIN管道中。

其中context的类型是IOwinContext:

public interface IOwinContext
{
// Gets the Authentication middleware functionality available on the current request.
IAuthenticationManager Authentication { get; } // Gets the OWIN environment.
IDictionary<string, object> Environment { get; } // Gets a wrapper exposing request specific properties.
IOwinRequest Request { get; } // Gets a wrapper exposing response specific properties.
IOwinResponse Response { get; } // Gets or sets the host.TraceOutput environment value.
TextWriter TraceOutput { get; set; } // Gets a value from the OWIN environment, or returns default(T) if not present.
T Get<T>(string key); // Sets the given key and value in the OWIN environment.
IOwinContext Set<T>(string key, T value);
}

 运行结果:

如图 可以顺利解析到不同的访问Url,自然也就可以在后续的处理中做出不同的处理,直接分支处理或读取静态文件或者实现MVC架构等等……。

改用其他形式的Host和Server

上例中IIS同时充当了Host和Server的角色,

首先创建一个简单的Console应用程序,用Nuget添加Microsoft.Owin.SelfHost

以同样的方式添加Startup启动类

将控制台程序改造为Host

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

运行结果:

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>

路由配置

protected void Application_Start(object sender, EventArgs e)
{
// Registers a route for the default OWIN application.
RouteTable.Routes.MapOwinPath("/owin");
// Invokes the System.Action startup delegate to build the OWIN application and
// then registers a route for it on the given path.
RouteTable.Routes.MapOwinPath("/special", app =>
{
app.Run(OwinApp2.Invoke);
});
} 
public class OwinApp2
{
// Invoked once per request.
public static Task Invoke(IOwinContext context)
{
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync("Hello World 2");
}
}

自定义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);
}
}

注册:

public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<HelloWorldMiddleware>();
}
}

应用

ASP.NET Web Form,ASP.NET MVC5项目结合OWIN

由于ASP.NET Web Form和ASP.NET MVC5依赖于System.Web.dll中的很多类型,而在OWIN管道中,是无法提供这些依赖的。所以ASP.NET Web Form和ASP.NET MVC5不能作为一个中间件直接集成到OWIN管道中。

但在这些项目中,也可以添加Startup.cs, 指定成为OWIN的初始化类型,那么请求会先经过OWIN管道处理,最后转向ASP.NET Web Form或者ASP.NET MVC程序。这种方式,常常用来配置log, authentication, cache等等这些Middleware。

引入OWIN后的管道执行顺序

Web API作为Middleware注册到OWIN管道中

Web API由于无任何依赖于System.web.dll, 所以可以作为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);
}
}

ASP.NET 5

ASP.NET 5中终于去System.web.dll化,MVC,Web API都统一在了OWIN管道中。

ASP.NET 5 的 project.json 配置文件(Microsoft.Owin改做Microsoft.AspNet 了):

ASP.NET 5 中Startup.cs 的两个重要方法:

// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
// Add EF services to the services container.
services.AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(); // Add Identity services to the services container.
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration); // Add MVC services to the services container.
services.AddMvc(); // Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
// You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
// services.AddWebApiConventions();
} // Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
// Configure the HTTP request pipeline.
// Add the console logger.
loggerfactory.AddConsole(); // Add the following to the request pipeline only in development environment.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
app.UseBrowserLink();
app.UseErrorPage(ErrorPageOptions.ShowAll);
app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
}
else
{
// Add Error handling middleware which catches all application specific errors and
// send the request to the following path or controller action.
app.UseErrorHandler("/Home/Error");
} // Add static files to the request pipeline.
app.UseStaticFiles(); // Add MVC to the request pipeline.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }); // Uncomment the following line to add a route for porting Web API 2 controllers.
// routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});
}

  ConfigureServices 在运行时的时候被运行,Configure 运行在 ConfigureServices 之后,查看 ConfigureServices 中的 Add 方法注释,你会发现最后一个单词总是 container(容器),这是怎么回事呢,其实就是往Ioc容器中注入类型依赖的对象,这些类型对象的管理都是在 Owin 管道中的,你只需要在 ConfigureServices 中使用 Add 方法注册相应模块就可以了,其他的东西 ASP.NET 5 会帮你完成,而 Configure 是什么作用呢?我自己觉得它是配置模块的一个“配置”,用户你使用中间件或者应用程序的一个配置,比如,你使用 app.UseCookieAuthentication 进行配置用户验证的一些操作,你查看 UseCookieAuthentication 的定义,会发现其命名空间为 Microsoft.AspNet.Builder.CookieAuthenticationExtensions,所在程序集为 CookieAuthenticationExtensions(Owin 中间件),查看 Configure 中其他 Use 使用,你同样会发现命名空间都是 Microsoft.AspNet.Builder 开头,之前说 Owin 是一种协定,Extensions 就是一种中间件和应用程序的扩展,但都必须符合此协定,这样才会有无限可能。

Asp.Net MVC<九>:OWIN,关于StartUp.cs的更多相关文章

  1. 学习ASP.NET MVC(九)——“Code First Migrations ”工具使用示例

    在上一篇文章中,我们学习了如何使用实体框架的“Code First Migrations ”工具,使用其中的“迁移”功能对模型类进行一些修改,同时同步更新对应数据库的表结构. 在本文章中,我们将使用“ ...

  2. 如何在 asp.net core 3.x 的 startup.cs 文件中获取注入的服务

    一.前言 从 18 年开始接触 .NET Core 开始,在私底下.工作中也开始慢慢从传统的 mvc 前后端一把梭,开始转向 web api + vue,之前自己有个半成品的 asp.net core ...

  3. 学习ASP.NET MVC(十一)——分页

    在这一篇文章中,我们将学习如何在MVC页面中实现分页的方法.分页功能是一个非常实用,常用的功能,当数据量过多的时候,必然要使用分页.在今天这篇文章中,我们学习如果在MVC页面中使用PagedList. ...

  4. 学习ASP.NET MVC(七)——我的第一个ASP.NET MVC 查询页面

    在本篇文章中,我将添加一个新的查询页面(SearchIndex),可以按书籍的种类或名称来进行查询.这个新页面的网址是http://localhost:36878/Book/ SearchIndex. ...

  5. 学习ASP.NET MVC(一)——我的第一个ASP.NET MVC应用程序

    学习ASP.NET MVC系列: 学习ASP.NET MVC(一)——我的第一个ASP.NET MVC应用程序 学习ASP.NET MVC(二)——我的第一个ASP.NET MVC 控制器 学习ASP ...

  6. 学习ASP.NET MVC系列 - 还有比这更简炼的吗?把复杂的事情变简单了,贡献啊!

    转自

  7. ASP.NET Core 基础知识(四) Startup.cs类

    ASP.NET Core应用程序需要一个启动类,按照约定命名为Startup.在 Program 类的主机生成器上调用 Build 时,将生成应用的主机, 通常通过在主机生成器上调用 WebHostB ...

  8. ASP.NET Core 菜鸟之路:从Startup.cs说起

    1.前言 本文主要是以Visual Studio 2017 默认的 WebApi 模板作为基架,基于Asp .Net Core 1.0,本文面向的是初学者,如果你有 ASP.NET Core 相关实践 ...

  9. bootstrap-data-target触发模态弹出窗元素的data使用 data-toggle与data-target的作用 深入ASP.NET MVC之九:Ajax支持 Asp.Net MVC4系列--进阶篇之AJAX

    bootstrap-data-target触发模态弹出窗元素的data使用 时间:2017-05-27 14:22:34      阅读:4479      评论:0      收藏:0      [ ...

随机推荐

  1. 基本动画CABasicAnimation - 完成之后闪回初始状态

    基本动画CABasicAnimation 结束之后,默认闪回初始状态,那怎么解决呢? position需要设备两个属性: // MARK: - 结束后不要闪回去 anim.removedOnCompl ...

  2. Android自定义控件6--轮播图广告的实现

    本文接着实现轮播图广告的监听滚动 本文地址:http://www.cnblogs.com/wuyudong/p/5920757.html,转载请注明源地址. 首先添加布局文件,实现小白点 shape_ ...

  3. ios 提取html 字符串中的img 的地址(图片地址)

    本文原文地址 http://www.cnblogs.com/qianLL/p/6082287.html 有时候 后台返回的是一串html'字符串 我们需要把里面的图片地址提取出来  这个关键就是一个正 ...

  4. TortoiseSVN提交提示423 Locked的解决办法

    往svn上提交文件时,文件可能被另一个人占用,这时提交就会报423Locked错误. 此办法是阅读官方文档(TortoiseSVN-1.6.16-zh_CN.pdf) 4.21 锁部分提供的办法: 首 ...

  5. 基于Windows 10平台的PM2.5检测器制作

    本篇文章详细讲解了如何利用SDS011激光式PM2.5传感器.HC-06蓝牙模块和Windows 10设备完成一个简单的PM2.5检测器及其应用程序的开发.该检测器使用蓝牙完成数据输出,方便设备连接, ...

  6. mysql慢查询日志分析工具 mysqlsla(转)

    mysql数据库的慢查询日志是非常重要的一项调优辅助日志,但是mysql默认记录的日志格式阅读时不够友好,这是由mysql日志记录规则所决定的,捕获一条就记录一条,虽说记录的信息足够详尽,但如果将浏览 ...

  7. jQuery 中的 39 个技巧

    1.当document文档就绪时执行JavaScript代码. 我们为什么使用jQuery库呢?原因之一就在于我们可以使jQuery代码在各种不同的浏览器和存在bug的浏览器上完美运行. <sc ...

  8. 利用httpd对tomcat进行负载均衡配置

    实验系统:CentOS 6.6_x86_64 实验前提:提前准备好编译环境,防火墙和selinux都关闭 实验说明:本实验共有2台主机,IP分配如拓扑 实验软件:jdk-8u60-linux-x64 ...

  9. .NET 响应式自动缩略图服务器

    做互联网网站,总是会涉及到缩略图问题,之前一直是在上传图片时生成不同尺寸的缩略图,一直感觉又费力又不好管理,之后就写子 ThumbnailServer 用于部署一个图片服务器,在使用图片时才将图片转为 ...

  10. execve(file, argv, env)参数argv获取字符串个数

    /* Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU ...