ASP.NET 5 引入了一个新型的运行时,让我们可以现场交付模式组合式构建应用程序,而不依赖于宿主机上的.NET框架。这种新模式为我们提供了命令行工具(DNVM、DNX、DNU)用于管理我们的.net 版本,依赖的库和运行环境,我们可以不需要Visual Studio,只需要一个文本编辑器和命令行就可以开发一个应用程序。
了解.NET 版本管理器 (DNVM) 之间 ,.NET 执行环境 (DNX) 和.NET 开发实用程序 (DNU) 之间的关系是开发 ASP.NET 5的根本。在这篇文章我们将看看在CentOS安装并使用 DNVM,DNX 和 DNU ,从命令行和文本编辑器开发一个简单应用程序,如果你使用docker,这些命令和docker还真是很像。
DNVM ( .NET Version Manager ):由于要实现跨平台的目录,微软提供了 DNVM 功能, DNVM 是 ASP.NET 最底层的内容,它是一组 Powershell 脚本,用于启动指定版本的 ASP.NET 运行环境,并且可以在同一台机器的同一时间点上通过使用 Nuget 工具来管理各种版本的 ASP.NET 运行环境( DNX ),以及进行相应的升级操作。
DNX ( .NET Execution Environment ): DNX 是 ASP.NET 程序的运行环境,用于启动并运行 ASP.NET 程序。该运行环境包括了编译系统、 SDK 工具集、 Native CLR 宿主环境。可以使用 DNVM 管理各种版本的 DNX ,如 dnvm list 命令可以列出所有可用的 DNX 环境,而 dnvm install 1.0.0-beta4 则可以将指定版本的 DNX 安装到 .dnx 文件夹,你可以在 %USERPROFILE%/.dnx/runtimes 目录下找到已安装所有版本的 DNX 。不同的操作系统有不同的 DNX 版本。
dnx.exe :dnx.exe 是用于启动自宿主环境( Self-Hosting )的命令行工具,在使用命令行代码进行自宿主环境启动程序时, dnx 负责查找并调用 CLR Native Host , dnx 命令是整个运行环境的入口点,你可以使用 dnx run 来启动程序。
dnu ( DNX Utility ) : 是一个命令行的包管理器,包含在 DNX 内,所以只要安装了 DNX ,就可以使用 dnu 命令, 其可以用于恢复程序包、安装程序包、部署程序包等等,比如把 project.json 里自定义的程序集自动下载下来进行使用。
DNX 架构及运行原理
DNX 是 ASP.NET 程序运行的核心,其遵循如下两个准则:
DNX 执行环境的分层架构如下:
该层的功能非常简单,主要就是用于查找并调用 Layer 1 里的 CLR Native Host ,并将系统相关的参数传递给 native host ,以便后续使用。目前 Windows 下使用 DNX.exe 来处理这个事情,而 IIS 也提供了一个中介(网站 bin 目录下提供一个 AspNet.Loader.dll )可以将请求转发给 Native Host ;而 Linux 和 Mac 则通过其相应版本的 dnx 来支持这项功能。
DNX 用法:
dnx . exe -- lib {paths} -- appbase {path} [ ProgramName ]
--lib {paths} :程序集 dll 的保存地址(一般是引用的第三方程序集和项目预编译程序集),该地址是 Layer 2 层的托管代码入口点可以加载程序集的地方。
--appbase {path} :程序保存的目录,默认为 %CD% 。
[ProgramName] :程序名称,该程序所在的程序集(或者是含有 Programe::Main 的 dll )保存在 --lib 路径下,默认值是 appbase/project.json 里的 name 。大多数情况下,该名称都是包含着加载链的程序宿主( Microsoft.Net.ApplicationHost )。但是,如果你的程序包含了入口点( Main 方法),并被编译到 --lib 目录下的话,你就可以使用该程序集的名称作为 [ProgramName] ,这种方式将完全忽略加载链并直接启动你的程序。
这一层的内容依赖于你所选择呢 CLR 版本,该层有如下两个职责:
Layer 2 : Managed Entry Point
Layer 2 层(托管代码入口)是编写托管代码的第一层,其职责如下:
Layer 3 : Application host/Application
如果开发人员将整个程序编译成程序集放在 libpath 目录下,那该层就是你的应用程序了。使用的时候,将含有程序入口点的程序集名称作为 [ProgramName] 的参数传入即可, Layer 2 层会直接调用该程序集。
不过,一般其它情况下,都会使用一个应用程序宿主( Application host )来解析程序的依赖内容并启动运行程序。 Microsoft.Net.ApplicationHost 是运行环境提供的应用程序宿主,并拥有如下职责:
Layer 4 : Application
这一层,就是开发人员开发的程序,其运行在应用程序宿主之上。
要对 ASP.NET 5 程序的运行环境 DNX 进行配置,首先需要安装并配置 DNVM , CentOS 等 Linux 系统上需要先安装 Mono ,可以参照文章 CentOS 7 上部署 Mono 4 和 Jexus 5.6 。然后运行下面命令
curl -sSL https://raw.githubusercontent. com /aspnet/Home/master/dnvminstall. sh | sh && source ~/.dnx/dnvm/dnvm. sh
[root@Mono ~]# curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | DNX_BRANCH=dev sh && source ~/.dnx/dnvm/dnvm.sh
Downloading dnvm as script to '/root/.dnx/dnvm'
Appending source string to /root/.bash_profile
Type 'source /root/.dnx/dnvm/dnvm.sh' to start using dnvm
运行命令 dnvm :
上述 DNVM 安装以后,系统会将 dnvm 文件复制到 /root/.dnvm 目录,并将 /root/.dnvm 目录添加到环境变量中,以便全局都可以使用。注意:这里只是安装了 DNVM ,并没有安装任何版本的 DNX ,要安装 DNX 的话,可以通过运行 dnvm 或 dnvm help 来查找相关的命令,具体命令如下:
dnvm upgrade [-x86][-x64] [-svr50][-svrc50] [-g|-global] [-proxy < ADDRESS > ]
dnvm install < semver > | < alias > | < nupkg > |latest [-x86][-x64] [-svr50][-svrc50] [-a|-alias < alias > ] [-g|-global] [-f|-force]
dnvm use < semver > | < alias > |none [-x86][-x64] [-svr50][-svrc50] [-p|-persistent] [-g|-global]
dnvm list // 列出所有已安装的 DNX 版本
dnvm alias // 列出所有定义了别名的 DNX 版本
dnvm alias < alias > // 显示定义了别名的 DNX 名称
dnvm alias < alias > < semver > [-x86][-x64] [-svr50][-svrc50] // 给指定的 DNX 版本设置别名
管理程序集的 dnu 命令和 feed 源配置
通过dnu命令进行包管理的时候,通常使用如下命令:
dnu restore:查询程序的所有依赖包,并将其全部下载到packages目录,该命令会下载整个依赖包以及这些依赖包所依赖的其它依赖包。
dun install <package id>:该install命令用于下载指定的程序包并添加到程序中。
dun publish:该命令会将你的程序打包到一个可以运行的自包含目录中。其会创建如下目录结构:
output/
output/packages
outpot/appName
output/commandName.cmd
packages目录包含所有应用程序需要的程序包。
appName目录包含所有应用程序的代码,如果引用了其它项目,则在引用的其它项目也会创建各自项目的同级目录,即生成的目录会和AppName同级。
publish命令,会将project.json中的commands节点中的各种命令,分别生成响应的命令行文件,如commands里的web命令,我们就可以通过dnx web(格式:dnx <command>)开运行它。
由于dnu在内部使用了Nuget命令,进行程序包的管理,所以使用的时候要正确配置Nuget的feed源,目前ASP.NET 5相关的包都在myget feed上,所以我们需要添加这个feed才能正常运行。这些配置信息在*nix下Mono使用的~/.config/NuGet/NuGet.config文件中进行管理,示例如下:
我们使用 vim 和 dnx/dnu 命令行构建一个简单的程序,创建一个目录 dnx_demo, 在目录下创建一个 project.json 文件,包含下面内容:
{
"version": "1.0.0-*",
"description": "geffzhang demo project",
"commands": {
"runme": "dnx_demo"
},
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Console": "4.0.0-beta-22816",
"Microsoft.CSharp": "4.0.0-beta-22816"
}
}
}
}
上面我们定义了一个命令"runme",它指向的是工程名称:dnx_demo。我们可以通过命令行使用dnx运行我们的项目,我们的项目指向传统的.NET Framework (dnx451) 和 .NET Core (dnxcore50),所以我们可以用dnx和.net fx运行。
然后在创建一个 Program.cs文件,内容如下:
using System;
namespace dnx_demo
{
public class Program
{
public void Main(string[] args)
{
Console.WriteLine("No Visual Studio Here!!");
Console.Read();
}
}
}
保存后,我们先运行命令 dnu restore ,将我们依赖的程序包下载到 package 目录。
目前我们运行的程序还仅仅是一个非常简单的控制台程序,还没有包括EF, SignalR, Identity等复杂组件,但从整个部署过程中,我们可以感觉到其实差距已经很小. 首先运行和部署环境DNVM和dnu, dnx命令和VS 2015的环境是一致的,而且组件包都是从Nuget上获取,这和标准的Windows开发环境并没有太大区别。