2014/11/29 技术探讨

    就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview。

    Visual Studio 2015 Preview 除了给我们带了了C# 6.0的新语法、跨移动的开发以外,还给我们带来了ASP.NET5(也就是之前被称作下一代ASP.NET的ASP.NET vNext)。于是,本人也先睹为快的安装上了PreView版的Visual Studio 2015,再探这个万众期待的ASP.NET5。有读者可能会问到,为何用‘再’这个字眼,之前是否已经有探索过?对的,早VisualStudio 2014 CTP的时代,不少对vNext(当时对ASP.NET5的称呼)抱有巨大兴趣的朋友就提前尝鲜,而那个时候也是本博客(jhonge.net)决定开始编码的阶段,迫切需要对Web进行选型,也就是那个时候对ASP.NET vNext进行了一番初探(不过这些都是题外话了)。我们还是马上进入本文讨论的主题。

    本文中,我们将讨论:

      1、ASP.NET5(Web)中,各个目录以及文件的介绍

      2、KRuntime的简介

      3、ASP.NET5与OWIN的关系 


     一、ASP.NET5中各个目录以及文件的介绍

    ASP.NET5主要提供了两种应用程序,其一就是ASP.NET5控制台程序,另外一个是ASP.NET Web 应用程序。

   我们选择新建一个Web应用程序,得到如下图所示:

    由于One ASP.NET战略的关系,从Visual Studio 2013(.NET FrameWork 4.5)开始,在ASP.NET Web Application中ASP.NET WebFrom与ASP.NET MVC/WebAPI已经合并为同一个的选项卡,用户在选择该选项卡创建新的Web应用程序之后再根据自身的需求选择想创建的站点类型,Visual Studio会根据用户的期望自动的引入相应的预设资源以及创建相应的预设目录。

    由图中,我们也可见前面的六项是“经典”的One ASP.NET项目,后面的两项则是我们本文中的主角——ASP.NET5 Web应用程序。

    对于ASP.NET 5 Web应用程序,它主要泛指ASP.NET5 MVC应用程序(也就是一些读者所称的MVC6),而我们所熟知的ASP.NET WebForm已经被剔除在ASP.NET5之中,这也意味着我们再也无法拖控件了,这点确实是有点遗憾,或许是WebForm与System.Web结合过紧亦或其他原因(专利技术?)从而导致它从ASP.NET5中被剔除(图中也显示我们无法勾选想创建的类型)。

    对于类库的使用,ASP.NET5使用了一种名为“ASP.NET 5 Class Library”的专用库,这种全新的专用库使用方式于之前的.NET普通类库还是有少少区别。这里也有一点值得各位读者非常注意的,那就是这种专用库与普通类库是互不兼容的,ASP.NET5也无法直接使用普通的类库,这点非常令人难堪,不过值得安慰的是,微软正在火速的对现有的类库进行ASP.NET5的转移,每周都有大批的专用库转换完成并上线。有兴趣的读者可以到MyGet(需要翻~@墙)进行查阅。对于一些私有库,我们则需要将原有的CS文件抽出来,然后重新添加进专用库中,重新发布(或许以后会有个批量自动转换工具)。发布后的库文件,我们需要对其进行重新的单元测试,确认无误后方可使用。

    我们先新建一个ASP.NET5 Start Web应用程序,创建后如下图所示(高分辨率大图,可以单独拖出来看):

    可见Visual Studio自动默认的显示了一个ASP.NET5的欢迎页面,我们可以从上面得到一些关于ASP.NET5的有关消息,再看看右边的项目截图,如下图所示:

 

    我们可以看到,在ASP.NET5中,它划分了一个隶属于解决方案的Solution Item目录和一个src(顾名思义,源代码)的目录,Solution Item我们忽略不看,我们将目光投向其中的WebApplication,它是我们刚新建的项目,下面我们相对里面包含的目录以及关键的文件进行一番说明。

    “wwwroot”:一看这名字,或许许多人会认为这个是网站根目录的意思,其实不然,这个目录的作用并非字面意思,实际上这个目录的作用是放置静态文件的,样式文件放css,第三方的库文件放lib,自己创建的脚本文件放script(默认没有创建)。

    “Dependence”:依赖,这里就是字面意思了,严格来说,这个“Dependence”并非文件夹,而是Visual Studio将一些项目配置文件中的配置以可视化的方式将它们的配置(依赖或者打包等)显示出来,当然也可以进行可视化操作了(仅限可视化删除)。

    “References”:这个只要是懂.NET的人都知道,显示您的程序用了啥程序集,在Project.json中进行配置(稍后介绍Project.js)。

    “Controller”:大名鼎鼎的MVC中的C字头。

    “Migrations”:EntityFramework的数据迁移文件,一般由VisualStudio自动托管。

    “Models”:MVC中的M字头。

    “Views”:MVC中的V字头。

    “bower.json”:一个包管理器,作用就是自动把前端的包搞到本地。

    “config.json”:作用跟ASP.NET的WebConfig中的部分节点类似,作用就是将一些譬如链接字串、EntityFrameWork的配置、Log4Net等配置信息写到此处,并在Startup中将此文件读取并加入到ASP.NET5的环境中。除了有默认为json格式的配置外,ASP.NET5还支持另外配置方式——XML,作用是一致的。

    “gruntfile.js”:作用与MVC5以及5-的BundleConfig相同,也是通过配置将一堆的静态文件进行打包压缩,并通过一个Request把这些文件全部下载下来。

    “package.json”:在此(ASP.NET5)之前,“package.json”被用作一个程序集组件信息清单,在这个清单中记录着所有通过NuGet获得的组件以及它的版本信息,NuGet本身就是通过这个清单列表来维护它的组件。但在ASP.NET5中,项目所依赖的组件已经由package.json移到了project.json中,因此package.json的功能已经被削减。

    “Project_Readme.html”:这个不解析了,一个“ReadMe”。

    “project.json”:刚才说到项目用到的组件清单已经移到该文件中,是的,而事实上,这个文件可以说是整套项目中最重要的文件之一。它包含了项目启动所需要的几乎所有基础配置,包括NuGet的组件清单、程序集的依赖、使用哪种Host方式,监听那个端口,以及一些中间件的配置等。

    “Startup.cs”:如果对Microsoft.OWIN有所了解的读者,那一定可以下意识的联想到这个文件是干嘛的,对的,ASP.NET5中“Startup”文件与基于Microsoft.OWIN的OWIN框架中的“Startup”文件的作用是相同的,但别误会了,ASP.NET5并不是基于Microsoft.OWIN打造的(在第三节会介绍),因此它们作用差不多,但不是同一个东西。

    目录组成已经文件的介绍大概就这么多,至于每个文件的详细介绍以及用法,由于文章篇幅关系以及官方暂未公布更多的资料,这里就不再作展开介绍了,有机会我再来跟各位读者进行展开的讨论学习。

 

    二、KRuntime的简单介绍

    关于KVM、KLR为何叫‘K’,这个众说纷纭,有人说是K For Katana,也有人说K For Kool,当然也有人说K is the next J。不管怎么样,我们都无法知道为何叫做K,我们只知道这个K来源于Project K。至于Project K的内容,恐怕只有核心的Team成员才通晓。关于KVM最详细最权威的解析以及最新的发展介绍,各位读者可以到GitHub/Wiki中找到,这里我们仅对其作抛砖引玉。

    为了介绍这个新概念的东西,我们需要先上一张图:

 

    由图中我们可以知道,KRuntime大概分为这么三大层:以KHost方式存在的Layer0、作为KRuntime的Layer1-Layer3以及应用程序层Layer4。下面我们再介绍下每个Layer层的作用:

    Layer0:Layer0层作为Host层,它提供了查找并调用CLR的功能,所有的请求将通过它来进行初步处理并对非静态请求推送到Layer1层,它的功能就跟IIS相当,而在ProjectK中,该层的实例就是KLR.exe。

    Layer1:从Layer1层开始,请求正式进入到KRuntime的环节,Layer1层的工作内容是启动CLR,装载Coreclr.dll(这个玩意会在发布之后的/approot/packages/KRE-XXXXX/bin中可以找到,会自带的),提供Layer0层的CLR入口。

    Layer2:Layer2层的名字叫做‘Managed Entry Point’,中文翻译为“入口点管理”,根据官方的介绍,这层的是托管代码的第一层,它的作用是创建LoaderContainer并根据CLR的请求提供ILoader,ILoader负责根据名称来加载程序集。此外Layer2层还用于调用Layer3中程序的主入口点。

    Layer3:如果您已经把项目发布到硬盘当中,那么您发布的东西就是Layer3中的内容了,要激活您的发布(Layer3的内容),您需要提供发布的这个项目的项目名(ProjectName)作为项目的程序入口点(程序会自动寻找ProjectName.Startup),Layer2会根据给出的程序名(ProjectName)调用您的项目程序入口并根据项目的Project.json清单检查程序集是否完备,如果程序集不完备,它将自动的根据清单中的依赖关系,从NuGet、MyGet等源中自动解决依赖。同时,Layer2中会使用一个ILoader来自动加载项目的程序集组件。

    Layer4:顾名思义,就是加载到内存后正在运行的您的程序。

    以上就是关于KRuntime的简单介绍,我们的ASP.NET5就处于Layer3以及Layer4之中,运行我们的ASP.NET5,我们的底层需要KRuntime的支撑,因此要激活(启动)我们的ASP.NET5程序,最简单的方式就是使用ProjectK中所提供的K Command,通过命令行的方式来启动我们的ASP.NET5。

    K Command目前包含了三种类型的命令。一种是单纯的‘K’,它是用于直接控制您的项目启动、关闭和构建(Build);另外一种是‘KVM’,它是管理您的KRE版本的,使用它我们可以列出本机中存在的KRE,也可以安装类型的KRE或者升级本机的KRE;最后一种就是‘KPM’,它的作用是管理您的项目中一些程序集组件包,其中最直接的用法就是KPM Restore直接用NuGet等源下载Project.json中列有的相关组件。

    不过即便K Command是如此的重要,但或许还是少有读者会直接接触它,原因就在于Visual Studio实在太贴心了。在Visual Studio 2015中发布项目时,IDE会通过图形化的界面让您选择合适的KRE版本,项目所需要用到的组件也统统的发布到“/approot/packages”中(KLR.exe也在里面),自动的帮我们解决了KRE和组件的完整性,在发布的根目录中,IDE还给我买你自动生成启动项目的批处理命令,我们只需要简单的双击即可启动我们的项目。

    但是随着时间的推移,KRE也会出现Mono版本,在非Windows中使用ASP.NET,那就没有这么方便了,我们需要老老实实的自己敲K Command,当然,本文也不是专门详解K Command的,希望能够获得更多关于K Command信息的读者,可以访问Version ManagerPackage Manager来获取。

 

    三、ASP.NET5与OWIN的关系

    在Visual Studio 2015发布之前,ASP.NET5当时被称作vNext,vNext作为微软发布的“下一代.NET”一直备受关注,与此同时,微软发起了一个全新的介于WebServer与WebApplication的协议“Open Web Interface for .NET”也即时OWIN。vNext中一个很重要的特点就是不再限于Windows中运行,微软主动的把vNext往跨平台.NET方向走;而OWIN协议的出现也是为了解决WebApplication与IIS之间紧密耦合的关系(实际上我们还是可以Host到其他WebServer的,这里我们就不作研讨了),OWIN协议也很大程度上让我们的.NET WebApplication得到了跨平台的功能。因此一时之间,不少的“同行”都想当然并自动代入的将这两者直接联系了起来,关于“OWIN即vNext”这种类似的说法也如潮水一般铺天盖地而来。(What?您还不懂OWIN是啥,那赶紧补补,建议参考《Linux.NET 学习手记7》、《Linux.NET 学习手记8》、《关于<Linux.NET学习手记(8)>的补充说明》以及OWIN Org)。

    但,OWIN真的就是vNext吗?我个人理解并不是的,OWIN是一个协议,它定义的内容是WebApplication与WebServer之间的通信协议,协议的核心内容也精简到只是一个单纯的OWIN字典,字典上面包含了一些比较原始的请求参数,只要支持并使用OWIN字典与WebApplication进行通信的WebServer我们便可以广义上认为这就是一个OWinHost(Katana、Jexus等),同样的只要兼容OWIN协议的框架我们也可以认为这是一个支持OWIN的框架(像NancyFX、SignalR、FubuMVC之类)。而vNext是什么?它是一个现成的构架,虽然它长得像其他的OWIN框架(准确来说是Microsoft.OWIN,都有Startup,并且都是通过Startup作为程序的入口点),但它的战略却与OWIN的提出是不同的,vNext的战略目标是云部署、云编译以及云优化,它是云战略的重要组成部分,当然跨平台也是它的其中之一的特点,但它并不是像OWIN一样为开放性解决WebServer与WebApplication之间的关系而提出。

    事实上,更具爆炸性的消息就是,vNext虽然也有Startup入口,并且也具有兼容Katana的功能,但它的中间件并非基于OWIN协议(OWIN 1.0)建立。关于这一点,在撰写本文的前两天时间中,大(Artech)所公布的一封与ASP.NET Team同证实了这个事实,以下是内容的节选:

 

    对此我们的LexLi童鞋也跟我们比较详细的解析了Katana与vNext之间的关系(以下原文):

      1.Katana是在vNext开始前就存在的OWIN实现,未必完全适合vNext的需要。

      2.vNext现在不基于Katana,但是兼容OWIN中间件。

      3.vNext定义的接口还是和Katana相似的,容易迁移。

      4.vNext完工的时候,OWIN标准也许也该升级了。

      5.反正都是开源的开放的。

    因此,我们现在已经可以很明确的得出了一个结论:“OWIN是OWIN,vNext是vNext,它们两者并不是同一个东西”。 


     嗯,好的,在本文中,我们借助Visual Studio 2015 Preview,给读者们简单介绍了下ASP.NET5(vNext)以及KRuntime,同时也与读者们一同梳理了一下vNext与OWIN之间的关系。虽然本文努力保证知识的正确性,但仍然可能会存在知识点的错漏,望各位读者以微软官方发布的消息为准,如果发现文中有错误或者不足的,欢迎与我联系提出,本人感激不尽。此外,有兴趣的读者,(打个广告)也可以到QQ群:373470340 找到我或与其他大牛一同探讨跨平台的技术。

  [ Linux.NET ]   [ Mono ]   [ .NET ]   [ vNext ]   [ ASP.NET5 ]
知识共享许可协议 本作品由小蝶惊鸿创作,采用知识共享署名 4.0 国际许可协议进行许可,转载时请保留本文署名及链接。