在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
https://msdn.microsoft.com/zh-cn/magazine/dn451439.aspx (Katana 项目入门) OWIN的全称是Open Web Interface For .Net。 OWIN提供的只是一种规范,而没有具体实现。其目的是在web服务器和应用程序组件之间隔离出一个抽象层,使它们之间解耦。 应用程序委托和环境字典OWIN将服务器与应用程序之间的交互减少到一小部分类型和单个函数签名,这个函数签名被称为应用程序委托(即 AppFunc): using AppFunc = Func<IDictionary<string, object>, Task>; 然后,这些组件链接成一个管道,基于 OWIN 的服务器将会向该管道推送请求。
一个符合OWIN的web服务器,需要将请求信息(应用程序状态、请求状态和服务器状态等所有相关信息)包装到一个字典里(应用程序委托上指定的 IDictionary<string, object>,这种数据结构称为环境字典),从而使得许多不同的框架和组件作者可以在一个 OWIN 管道中进行互操作,而不必强制实施对特定 .NET 对象模型的协议。 虽然任何键/值数据都可以插入到环境字典中,但 OWIN 规范为某些 HTTP 核心元素定义了键:
随着请求在OWIN管道中流动,每个中间件(Middleware,集成到管道中的组件或应用程序)所要做的就是读取、修改这个字典的数据。最后,Web服务器得到这个层层处理过的字典,然后输出网页到客户端。
与ASP.NET管道相比,OWIN规范非常简洁,且并没有引用.Net Framework中的System.Web.dll。 1. 新的组件能够非常简单的开发和应用 KatanaKatana 项目是 Microsoft 创建和推出的基于 OWIN 的组件和框架集合。 https://katanaproject.codeplex.com 但上面这个项目最后一次提交是15年1月 目前它的托管代码已经被拆分: New 'Katana' Source:
Katana 体系结构
———— 使用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。 默认名称匹配 使用OwinStartup Attribute 在配置文件的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 5ASP.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 就是一种中间件和应用程序的扩展,但都必须符合此协定,这样才会有无限可能。 |
请发表评论