[转]通过几个Hello World感受.NET Core全新的开发体验

通过几个Hello World感受.NET Core全新的开发体验

2016年07月05日 17:17:00?zhao1949?阅读数:42491?标签:?.net?更多

个人分类:?.net

http://www.cnblogs.com/artech/p/net-core-hello-world.html

******************************************************************

2016年6月27日,这是一个特殊的日子,微软全新的.NET开发平台.NET Core的RTM版本正式发布。我个人将.NET Core的核心特性归结为三点,它们的首字母组成一个非常好记的简称——COM,分别代表的含义Cross-Platform、Open-Source和Modularization???NET Core应用的方式与之前具有非常大的变化,对于那些尚未体验过.NET Core的朋友,我希望通过本篇文章创建的这j几个Hello World应用可以很容易地带你们快速入门。

首先我们会介绍如何构建.NET Core应用的开发环境。在这之后,我们会利用dotnet new命令行创建一个控制台类型的Hello World应用,这个简单的应用时后续几个Hello World应用的雏形,后者都是通过它改变而成。我们做的第一个改变是将它变成一个ASP.NET Core应用,并采用Self-Host的方式将它寄宿于这个控制台应用中。这个ASP.NET Core应用被进一步改造成一个ASP.NET Core MVC应用,我们会自行定义Controller和View已经路由。

目录

一、构建开发环境

二、执行dotnet new命令创建一个控制台应用

三、将应用修改成一个ASP.NET Core应用

四、自行指定监听地址

五、将应用修改成一个ASP.NET Core MVC应用

六、添加View


一、构建开发环境

根据自身的操作系统类型安装和运行环境.NET Core SDK、IDE和相关的工具

Windows:https://www.microsoft.com/net/core#windows

Linux

Ret Hat :https://www.microsoft.com/net/core#redhat

Ubuntu :https://www.microsoft.com/net/core#ubuntu

Debian :https://www.microsoft.com/net/core#debian

Fedora:?https://www.microsoft.com/net/core#fedora

Centos:?https://www.microsoft.com/net/core#centos

Opensuse:?https://www.microsoft.com/net/core#opensuse

Mac:?https://www.microsoft.com/net/core#macos

Docker:https://www.microsoft.com/net/core#docker

二、执行dotnet new命令创建一个控制台应用

我们直接启动命令行工具,为创建的Hello World应用创建一个根目录(%USERPROFILE% projects/helloworld)。在将该目录设置为当前目录后,我们按照如下的方式执行“dotnet new”命令。源代码下载:netcore.helloworld1

dotnet new命令会为我们创建一个由如下两个文件组成的控制台应用。

作为程序入口的Main方法定义在Program.cs文件中,如下所示的代码片段体现了该文件的整体定义,我们可以看到Main方法仅仅是在控制台上打印出“Hello World”字样而已。

? 1:usingSystem;

? 2:namespaceConsoleApplication

? 3:{

? 4:publicclassProgram

? 5:{

? 6:publicstaticvoidMain(string[] args)

? 7:{

? 8:Console.WriteLine("Hello World!");

? 9:}

? 10:}

? 11:}

我们创建的控制台项目直接映射为一个目录,项目自身的设置定义在project.json这个文件中,该文件的整体定义反应在如下所示的代码片段中。整个文件由四个节点组成,其中version和buildOptions用来定义目标项目的版本和编译选项。dependencies在用来存放针对NuGet包的以来。我们创建的项目可以针对一个或者多个Framework(比如我们希望创建的可以同时在.NET Framework和.NET Core上运行),支持的Framework定义在frameworks节点下。如果添加了多个Framework,并不是说最终生成的应用可以同时在这些Framework中运行,而是说源文件在编译的时候会针对这些Framework生成对应的程序集。

? 1:{

? 2:"version":"1.0.0-*",

? 3:"buildOptions": {

? 4:"debugType":"portable",

? 5:"emitEntryPoint":true

? 6:},

? 7:"dependencies": {},

? 8:"frameworks": {

? 9:"netcoreapp1.0": {

? 10:"dependencies": {

? 11:"Microsoft.NETCore.App": {

? 12:"type":"platform",

? 13:"version":"1.0.0"

? 14:}

? 15:},

? 16:"imports":"dnxcore50"

? 17:}

? 18:}

? 19:}

对于传统的.NET项目来说,如果我们需要调用某个API,需要添加所在程序集的引用。对于.NET Core来说,所有使用到的程序集都被打包成一个NuGet包,所以针对程序集的直接依赖转变成针对某个NuGet包的依赖。针对NuGet的依赖主要有两种类型,一种是针对所有Framework的,它们会直接定义在dependencies节点下,另一种则是针对某个具体Framework的,定义的定义为当前Framework节点下的dependencies子节点。我们定义在Project.json中的设定的NuGet包可能尚未在本地安装,我们可以执行dotnet restore命令获取并在本地安装所有需要的NuGet包。一旦完成了针对NuGet包的回复操作,我们就可以直接执行dotnet run命令来启动应用。在这期间,我们的应用实际上会经历一个编译的过程,我们也可以执行dotnet build命令对其实施编译。如下面的代码片段所示,我们分别先后执行restore、build和run三个命令,目标程序最终得以执行。

三、将应用修改成一个ASP.NET Core应用

接下来我们将这个控制台应用改造成一个最简单的ASP.NET Core应用。IDE的选择,我们可以使用VS 2015,也可以使用VS Code,假设我们选择前者。我们以开启项目(File->Open->Project/Solution)的方式打开project.json后,相当于开启了整个控制台项目。ASP.NET Core的核心管道定义在NuGet包“Microsoft.AspNetCore.Hosting”中,以Self-Host的方式寄宿ASP.NET Core应用还需要一个Server,我们选择的是定义在“Microsoft.AspNetCore.Server.Kestrel”这个NuGet包中的KestrelServer,所以我们第一步需要做的就是在project.json中添加针对这两个NuGet包的依赖。源代码下载:netcore.helloworld2

? 1:{

? 2:"version":"1.0.0-*",

? 3:"buildOptions": {

? 4:"debugType":"portable",

? 5:"emitEntryPoint":true

? 6:},

? 7:"dependencies": {

? 8:"Microsoft.AspNetCore.Hosting":"1.0.0",

? 9:"Microsoft.AspNetCore.Server.Kestrel":"1.0.0"

? 10:},

? 11:"frameworks": {

? 12:"netcoreapp1.0": {

? 13:"dependencies": {

? 14:"Microsoft.NETCore.App": {

? 15:"type":"platform",

? 16:"version":"1.0.0"

? 17:}

? 18:},

? 19:"imports":"dnxcore50"

? 20:}

? 21:}

? 22:}

ASP.NET Core应用的寄宿依赖于一个WebHost对象,后者则通过对应的工厂WebHostBuilder创建,为此我们将针对WebHost的创建定义在作为入口点的Main方法中。如下面的代码片段所示,我们创建了一个WebHostBuilder对象,在调用其Build方法创建WebHost对象之前,我们先后调用了前者的UseKestrel和UseStartup方法。前者的目的在于注册上面提及的这个叫做KestrelServer的Server,后者则注册一个启动类型Startup。WeHost的Run方法一旦调用,意味着ASP.NET Core应用被启动。

? 1:usingSystem;

? 2:usingMicrosoft.AspNetCore.Hosting;

? 3:usingMicrosoft.AspNetCore.Builder;

? 4:usingMicrosoft.AspNetCore.Http;

? 5:

? 6:namespaceConsoleApplication

? 7:{

? 8:publicclassProgram

? 9:{

? 10:publicstaticvoidMain(string[] args)

? 11:{

? 12:newWebHostBuilder()

? 13:.UseKestrel()

? 14:.UseStartup()

? 15:.Build()

? 16:.Run();

? 17:}

? 18:}

? 19:}

ASP.NET Core应用的背后是一个由Server和Middleware工程的管道,Server实现针对请求的监听、接收和响应,而注册的Middleware则负责对请求进行处理。WebHostBuilder的UseKestrel方法为管道注册了必不可少Server,Middleware的注册在实现在由UseStartup方法注册的启动类型中。如下所示的是我们注册的Startup类型的定义,我们在Configure方法中调用ApplicationBuilder的扩展方法Run注册了唯一的Middleware,它对请求的处理逻辑简单而直接——直接响应一个“Hello World”字符串。

? 1:usingSystem;

? 2:usingMicrosoft.AspNetCore.Hosting;

? 3:usingMicrosoft.AspNetCore.Builder;

? 4:usingMicrosoft.AspNetCore.Http;

? 5:

? 6:namespaceConsoleApplication

? 7:{

? 8:publicclassStartup

? 9:{

? 10:publicvoidConfigure(IApplicationBuilder app)

? 11:{

? 12:app.Run(context=>context.Response.WriteAsync("Hello World"));

? 13:

? 14:}

? 15:

? 16:}

? 17:}

我们同样按照上面的方式执行dotnet restore和dotnet run命令,ASP.NET Core应用将被启动。

上控制台上的输出我们可以看出,ASP.NET Core启动后会绑定到默认的地址“http://localhost:5000/”来监听请求,所以我们可以利用浏览器向这个地址发送请求,应用处理请求后会按照如下的形式响应由注册的Middleware写入的“Hello World”。

四、自行指定监听地址

我们在利用WebHostBuilder创建WebHost,以及利用后者启动ASP.NET Core应用的整个过程中并没有显式指定Server监听的地址,在此情况下默认的监听地址“http://localhost:5000/”会被使用。我们也可以自行指定这个监听地址,该地址可以通过调用WebHostBuilder的扩展方法UseUrls来指定。如下面的代码片段所示,我们在利用WebHostBuilder创建WebHost之前调用UseUrls方法注册了两个监听地址“http://localhost:8888/“和“http://localhost:9999/”。源代码下载:netcore.helloworld3

? 1:usingSystem;

? 2:usingMicrosoft.AspNetCore.Hosting;

? 3:usingMicrosoft.AspNetCore.Builder;

? 4:usingMicrosoft.AspNetCore.Http;

? 5:

? 6:namespaceConsoleApplication

? 7:{

? 8:publicclassProgram

? 9:{

? 10:publicstaticvoidMain(string[] args)

? 11:{

? 12:newWebHostBuilder()

? 13:.UseKestrel()

? 14:.UseStartup()

? 15:.UseUrls("http://localhost:8888/","http://localhost:9999/")

? 16:.Build()

? 17:.Run();

? 18:}

? 19:}

? 20:}

当应用再次被启动后,监听地址将发生改变,我们可以改变浏览器的目标地址来对此做验证。

五、将应用修改成一个ASP.NET Core MVC应用

我们继续对上面这个ASP.NET Core应用进行改造,并将其构建成一个MVC应用。建立在ASP.NET Core的所有的开发框架都是通过注册到管道中的某一个或者多个Middleware实现的。针对MVC的Middleware实现了路由、Controller的激活、Action方法的执行以及View的呈现。相关的类型通过“Microsoft.AspNetCore.Mvc”这个NuGet包承载,所以我们需要添加这个NuGet包的依赖。简单起见,我们只需要直接将project.json中添加的“Microsoft.AspNetCore.Hosting”替换成“Microsoft.AspNetCore.Mvc”即可。

? 1:{

? 2:"version":"1.0.0-*",

? 3:"buildOptions": {

? 4:"debugType":"portable",

? 5:"emitEntryPoint":true

? 6:},

? 7:"dependencies": {

? 8:"Microsoft.AspNetCore.Mvc":"1.0.0",

? 9:"Microsoft.AspNetCore.Server.Kestrel":"1.0.0"

? 10:},

? 11:"frameworks": {

? 12:"netcoreapp1.0": {

? 13:"dependencies": {

? 14:"Microsoft.NETCore.App": {

? 15:"type":"platform",

? 16:"version":"1.0.0"

? 17:}

? 18:},

? 19:"imports":"dnxcore50"

? 20:}

? 21:}

? 22:}

ASP.NET Core MVC相关Middleware的注册同样实现在Startup类型的Configure方法中。如下面的代码片段所示,我们直接调用ApplicationBuilder的扩展方法UseMvc注册了这个Middleware。由于这个Middleware需要使用到相关的服务,所以我们在另一个名为ConfigureServices的方法中通过调用ServiceCollection的扩展方法AddMvc注册了这些服务。

? 1:usingMicrosoft.AspNetCore.Hosting;

? 2:usingMicrosoft.AspNetCore.Builder;

? 3:usingMicrosoft.AspNetCore.Http;

? 4:usingMicrosoft.Extensions.DependencyInjection;

? 5:

? 6:namespaceConsoleApplication

? 7:{

? 8:publicclassStartup

? 9:{

? 10:publicvoidConfigureServices(IServiceCollection services)

? 11:{

? 12:services.AddMvc();

? 13:}

? 14:

? 15:publicvoidConfigure(IApplicationBuilder app)

? 16:{

? 17:app.UseMvc();

? 18:}

? 19:}

? 20:}

对于一个MVC应用来说,任意一个请求都是指向定义在目标Controller的某个Action方法中,接下来我们就来定义如下一个HomeController。ASP.NET Core MVC不像之前的MVC版本要求Controller实现IController接口,它可以是一个普通一个以Controller为后缀命名的公共类型。我们在HomeController中定义的Action方法Index,该方法上应用HttpGetAttribute以特性注入的形式注册了模板为“/{name}”的路由。

? 1:usingSystem;

? 2:usingMicrosoft.AspNetCore.Mvc;

? 3:

? 4:namespaceConsoleApplication

? 5:{

? 6:publicclassHomeController

? 7:{

? 8:[HttpGet("/{name}")]

? 9:publicstringIndex(stringname)

? 10:{

? 11:return$"Hello {name}";

? 12:}

? 13:}

? 14:}

当我们按照上面的方式启动这个ASP.NET Core MVC应用后,如果我们利用浏览器访问与注册路由相匹配的目标地址(“http://localhost:9999/foobar”),可以得到如下所示的相应结果。源代码下载:netcore.helloworld4

六、添加View

接下来我们为上面这个MVC应用添加View。为此我们需要按照如下的方式改写HomeController。我们让它继承基类Controller,并改变Action方法Index的返回类型(IActionResult),该方法直接调用View方法返回只想默认View的ViewResult对象。再次之前,我们将传入的参数name保存在ViewBag中。

? 1:usingMicrosoft.AspNetCore.Mvc;

? 2:

? 3:namespaceConsoleApplication

? 4:{

? 5:publicclassHomeController: Controller

? 6:{

? 7:[HttpGet("/{name}")]

? 8:publicIActionResult Index(stringname)

? 9:{

? 10:ViewBag.Name = name;

? 11:returnView();

? 12:}

? 13:}

? 14:}

接下来我们来定义Action方法Index指向的这个View,按照约定我们应该将对应的Index.cshtml文件存放在/Views/Home目录下。该View定义如下。

? 1:<html>

? 2:<head>

? 3:<title>Hello</title>

? 4:<head>

? 5:<body>Hello, @ViewBag.Name</body>

? 6:</html>

由于我们使用到了Razor引擎,我们同样需要将相关的NuGet包“Microsoft.AspNetCore.Razor.Tools”按照如下的方式添加到project.json文件中。除此之外,基于View动态编译的需要,我们需要添加一个名为“preserveCompilationContext”的编译选项,并将其值设置为true。

? 1:{

? 2:"version":"1.0.0-*",

? 3:"buildOptions": {

? 4:"debugType":"portable",

? 5:"emitEntryPoint":true,

? 6:"preserveCompilationContext":true

? 7:},

? 8:"dependencies": {

? 9:"Microsoft.AspNetCore.Mvc":"1.0.0",

? 10:"Microsoft.AspNetCore.Razor.Tools": {

? 11:"version":"1.0.0-preview2-final",

? 12:"type":"build"

? 13:},

? 14:"Microsoft.AspNetCore.Server.Kestrel":"1.0.0"

? 15:

? 16:},

? 17:"frameworks": {

? 18:"netcoreapp1.0": {

? 19:"dependencies": {

? 20:"Microsoft.NETCore.App": {

? 21:"type":"platform",

? 22:"version":"1.0.0"

? 23:}

? 24:},

? 25:"imports":"dnxcore50"

? 26:}

? 27:}

? 28:}

除此之外,View的定位依赖于一个根路径,所以我们需要按照如下的方式调用WebHostBuilder的UseContentRoot方法将当前目录设置为此根目录。

? 1:usingMicrosoft.AspNetCore.Hosting;

? 2:usingMicrosoft.AspNetCore.Builder;

? 3:usingSystem.IO;

? 4:

? 5:namespaceConsoleApplication

? 6:{

? 7:publicclassProgram

? 8:{

? 9:publicstaticvoidMain(string[] args)

? 10:{

? 11:newWebHostBuilder()

? 12:.UseKestrel()

? 13:.UseStartup()

? 14:.UseContentRoot(Directory.GetCurrentDirectory())

? 15:.UseUrls("http://localhost:8888/","http://localhost:9999/")

? 16:.Build()

? 17:.Run();

? 18:}

? 19:}

? 20:}

当我们按照上面的方式启动这个ASP.NET Core MVC应用后,如果我们利用浏览器访问与注册路由相匹配的目标地址(“http://localhost:9999/foobar”),可以得到如下所示的相应结果。源代码下载:netcore.helloworld5

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • 2018.8.2星期四天气晴 亲子日记第148天 《父母规》第123天 上午姐妹俩辅导班都是十一点半结束,因...
    爱腾睿阅读 267评论 1 8
  • 小说《标准答案》 目录 上一章小说《标准答案》2.11时间的作用 2.12感恩 早上起来,纪梵去上班了,今天不用去...
    吴桐wutong阅读 486评论 0 1
  • 你想要的,岁月都会给你(不装逼那和咸鱼有啥区别)
    xyzsyy0102阅读 134评论 1 2
  • 我们在看别人文章的时候,喜欢品头论足。一篇文章是否有明确无误的“灵魂”,“骨架”是否健硕,“血肉”是否丰满,逻辑是...
    clover0305阅读 1,363评论 0 6