6

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

 2 years ago
source link: https://www.cnblogs.com/artech/p/net-core-hello-world.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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和相关的工具

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

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

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

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

   1: using System;
   2: namespace ConsoleApplication
   3: {
   4:     public class Program
   5:     {
   6:         public static void Main(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: using System;
   2: using Microsoft.AspNetCore.Hosting;
   3: using Microsoft.AspNetCore.Builder;
   4: using Microsoft.AspNetCore.Http;
   5:  
   6: namespace ConsoleApplication
   7: {
   8:     public class Program
   9:     {
  10:         public static void Main(string[] args)
  11:         {
  12:             new WebHostBuilder()
  13:             .UseKestrel()
  14:             .UseStartup<Startup>()
  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: using System;
   2: using Microsoft.AspNetCore.Hosting;
   3: using Microsoft.AspNetCore.Builder;
   4: using Microsoft.AspNetCore.Http;
   5:  
   6: namespace ConsoleApplication
   7: {    
   8:     public class Startup
   9:     {
  10:         public void Configure(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: using System;
   2: using Microsoft.AspNetCore.Hosting;
   3: using Microsoft.AspNetCore.Builder;
   4: using Microsoft.AspNetCore.Http;
   5:  
   6: namespace ConsoleApplication
   7: {
   8:     public class Program
   9:     {
  10:         public static void Main(string[] args)
  11:         {
  12:             new WebHostBuilder()
  13:             .UseKestrel()
  14:             .UseStartup<Startup>()
  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: using Microsoft.AspNetCore.Hosting;
   2: using Microsoft.AspNetCore.Builder;
   3: using Microsoft.AspNetCore.Http;
   4: using Microsoft.Extensions.DependencyInjection;
   5:  
   6: namespace ConsoleApplication
   7: {
   8:     public class Startup
   9:     {
  10:         public void ConfigureServices(IServiceCollection services)
  11:         {
  12:             services.AddMvc();
  13:         }
  14:         
  15:         public void Configure(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: using System;
   2: using Microsoft.AspNetCore.Mvc;
   3:  
   4: namespace ConsoleApplication
   5: {
   6:     public class HomeController
   7:     {
   8:         [HttpGet("/{name}")]
   9:         public string Index(string name)
  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: using Microsoft.AspNetCore.Mvc;
   2:  
   3: namespace ConsoleApplication
   4: {
   5:     public class HomeController: Controller
   6:     {
   7:         [HttpGet("/{name}")]
   8:         public IActionResult Index(string name)
   9:         {
  10:             ViewBag.Name = name;
  11:             return View();
  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: using Microsoft.AspNetCore.Hosting;
   2: using Microsoft.AspNetCore.Builder;
   3: using System.IO;
   4:  
   5: namespace ConsoleApplication
   6: {
   7:     public class Program
   8:     {
   9:         public static void Main(string[] args)
  10:         {
  11:             new WebHostBuilder()
  12:             .UseKestrel()
  13:             .UseStartup<Startup>()
  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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK