zoukankan      html  css  js  c++  java
  • 细说ASP.NET Core与OWIN的关系

      前言

      最近这段时间除了工作,所有的时间都是在移植我以前实现的一个Owin框架,相当移植到到Core的话肯定会有很多坑,这个大家都懂,以后几篇文章可能会围绕这个说下,暂时就叫《Dotnet Core踩坑记》吧,呵呵。

      接下来我对我在移植过程中发现的一些问题进行了总结,今天主要说说Owin。说到Owin就不能不提Katana项目和宇内大神的Tinyfox了,当然关于这两块内容这篇文章就不多涉及了,博友可以自己在博客园内搜索关于Owin的文章还是挺多的。

      Owin

      ASP.NET vNext刚推出的时候,号称是Owin的一个实现,在 http://owin.org 上,直到现在还保留着这样一段描述。

      Implementations

    •     Katana
    •     Freya
    •     ASP.NET vNext

      很多开发者纷纷实现着自己的Owin框架,也写很多应用到了实际的生产环境中,当然我也是其中一员。

      ASP.NET Core

      移植过程中,会发现有很多的不同,还有遇到新的API不知道怎么使用,这时候看文档还不如直接看源码来的痛快。

      在看完AspCore.Mvc后才发现,一点关于Owin的内容都没有;但很明显官方文档上说是支持Owin协议的,后来我硬着头皮去看了看KestrelHttpServerHttpAbstractions两个项目,后来才发现原来真的没有一点点的Owin协议内容啊(一定要给MS差评)。

      好吧,只能看看MS是怎么支持Owin的,在HttpAbstractions项目里发现了Microsoft.AspNetCore.Owin这样一个子项目,看完只是想说:“你这意思这叫向下兼容?” ,算了。 现在只要在Asp.net core项目里加入依赖Microsoft.AspNet.Owin就可以IApplicationBuilder接口的扩展方法UseOwin进行Owin中间件的调用。如下:

      添加依赖:

     "dependencies": {
        "Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
        "Microsoft.AspNet.Owin": "1.0.0-*"
      },

      在Startup中加入UseOwin:

    1 public void Configure(IApplicationBuilder app)
    2 {
    3     app.UseOwin(pipeline =>
    4   {
    5         pipeline(next => OwinHello);
    6   });
    7 }

      当然OwinHello的内容一定是一个标准Owin中间件的内容了:

     1 public Task OwinHello(IDictionary<string, object> environment)
     2 {
     3     string responseText = "Hello World via OWIN";
     4     byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
     5     var responseStream = (Stream)environment["owin.ResponseBody"];
     6     var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
     7     responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
     8     responseHeaders["Content-Type"] = new string[] { "text/plain" };
     9     return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
    10 }

      Kestrel

      既然新的服务器已经不在支持Owin协议了,那个是怎么通信的?

      这个问题在ASP.NET Core管道深度剖析系列文章中被提到过一些,其实每一个HttpContext在被创建出来都会依赖一个IFeatureCollection集合。

      IFeatureCollection这个接口用于描述某个对象所具有的一组特征,由一组Feature接口组成。

      列出其中一个IHttpConnectionFeature接口,用于获得Http的连接信息:

    public class HttpConnectionFeature : IHttpConnectionFeature
    {
            public string ConnectionId { get; set; }
            public IPAddress LocalIpAddress { get; set; }
            public int LocalPort { get; set; }
            public IPAddress RemoteIpAddress { get; set; }
            public int RemotePort { get; set; }
    }

      阅读kestrel源码,发现每一次接受tcp连接,都会将Http流,封装在一个帧Frame,它被描述成一个单向或双向的request和response。 并组装成特征集合供上层应用进行使用。

      最后

      最后就发一段Owin字典对应Feature的源码吧:

     _entries = new Dictionary<string, FeatureMap>()
                {
                    { OwinConstants.RequestProtocol, new FeatureMap<IHttpRequestFeature>(feature => feature.Protocol, () => string.Empty, (feature, value) => feature.Protocol = Convert.ToString(value)) },
                    { OwinConstants.RequestScheme, new FeatureMap<IHttpRequestFeature>(feature => feature.Scheme, () => string.Empty, (feature, value) => feature.Scheme = Convert.ToString(value)) },
                    { OwinConstants.RequestMethod, new FeatureMap<IHttpRequestFeature>(feature => feature.Method, () => string.Empty, (feature, value) => feature.Method = Convert.ToString(value)) },
                    { OwinConstants.RequestPathBase, new FeatureMap<IHttpRequestFeature>(feature => feature.PathBase, () => string.Empty, (feature, value) => feature.PathBase = Convert.ToString(value)) },
                    { OwinConstants.RequestPath, new FeatureMap<IHttpRequestFeature>(feature => feature.Path, () => string.Empty, (feature, value) => feature.Path = Convert.ToString(value)) },
                    { OwinConstants.RequestQueryString, new FeatureMap<IHttpRequestFeature>(feature => Utilities.RemoveQuestionMark(feature.QueryString), () => string.Empty,
                        (feature, value) => feature.QueryString = Utilities.AddQuestionMark(Convert.ToString(value))) },
                    { OwinConstants.RequestHeaders, new FeatureMap<IHttpRequestFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
                    { OwinConstants.RequestBody, new FeatureMap<IHttpRequestFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },
                    { OwinConstants.RequestUser, new FeatureMap<IHttpAuthenticationFeature>(feature => feature.User, () => null, (feature, value) => feature.User = (ClaimsPrincipal)value) },
                    { OwinConstants.ResponseStatusCode, new FeatureMap<IHttpResponseFeature>(feature => feature.StatusCode, () => 200, (feature, value) => feature.StatusCode = Convert.ToInt32(value)) },
                    { OwinConstants.ResponseReasonPhrase, new FeatureMap<IHttpResponseFeature>(feature => feature.ReasonPhrase, (feature, value) => feature.ReasonPhrase = Convert.ToString(value)) },
                    { OwinConstants.ResponseHeaders, new FeatureMap<IHttpResponseFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
                    { OwinConstants.ResponseBody, new FeatureMap<IHttpResponseFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },

      只能说还好,性能并没有太多的损耗,粘的不全,全的自己看吧 : ) 

      当然MS这样做也是有用意义的,他们不太喜欢字典的方式,于是用Feature这种方式将这些内容,"强类型化了"。这对于底层的Server来说,很快能基于这组特征二次开发出一套中间件来支持ASP.NET Core,当然直接在Server内实现这样性能也会更高。

      只能说API变化有点快吧,但是对于开源,看几天源码就全明白了,这对于我们dotnet开发者来说,真是大大的好事儿。

      

  • 相关阅读:
    OpenGL入门学习
    linux下安装sqlite3
    SQLite 之 C#版 System.Data.SQLite 使用
    .net程序运行流程
    一种简单,轻量,灵活的C#对象转Json对象的方案
    C# 获取Windows系统:Cpu使用率,内存使用率,Mac地址,磁盘使用率
    WPF中选择文件及文件夹
    要想创业成功,千万不能在这十个方面走弯路
    [译]Quartz.Net 框架 教程(中文版)2.2.x 之第三课 更多关于Jobs和JobDetails
    [译]Quartz 框架 教程(中文版)2.2.x 之第二课 Quartz API,Jobs和Triggers简介
  • 原文地址:https://www.cnblogs.com/maxzhang1985/p/5553335.html
Copyright © 2011-2022 走看看