[ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]
由于ASP.NET Core框架在本质上就是由服务器和中间件构建的消息处理管道,所以在它上面构建的应用开发框架都是建立在某种类型的中间件上,整个ASP.NET Core MVC开发框架就是建立在用来实现路由的EndpointRoutingMiddleware和EndpointMiddleware中间件上。ASP.NET Core MVC利用路由系统为它分发请求,并在此基础上实现针对目标Controller的激活、Action方法的选择和执行,以及最终对于执行结果的响应。在介绍的实例演示中,我们将对上面创建的ASP.NET Core作进一步改造,使之转变成一个MVC应用。
一、注册服务与中间件
ASP.NET Core框架内置了一个原生的依赖注入框架,该框架利用一个依赖注入容器提供管道在构建以及请求处理过程中所需的服务,而这些服务需要在应用启动的时候被预先注册。对于ASP.NET Core MVC框架来说,它在处理HTTP请求的过程中所需的一系列服务同样需要预先注册。对这个概念有了基本的了解之后,相信读者朋友们对如下所示的代码就容易理解了。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; namespace helloworld
{
class Program
{
static void Main()
{
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webHostBuilder => webHostBuilder
.ConfigureServices(servicecs => servicecs
.AddRouting()
.AddControllersWithViews())
.Configure(app => app
.UseRouting()
.UseEndpoints(endpoints => endpoints.MapControllers())))
.Build()
.Run();
}
}
}
整个ASP.NET MVC框架建立在EndpointRoutingMiddleware和EndpointMiddleware中间件构建的路由系统上,这两个中间件采用“终结点(Endpoint)映射”的方式实现针对HTTP请求的路由。这里所谓的终结点可以视为应用程序提供的针对HTTP请求的处理器,这两个终结点通过预先设置的规则将具有某些特征的请求(比如路径、HTTP方法等)映射到对应的终结点,进而实现路由的功能。对于一个MVC应用程序来说,我们可以将定义在Controller类型中的Action方法视为一个终结点,那么路由映射最终体现在HTTP请求与目标Action方法的映射上。
如上面的代码片段所示,我们先后调用了IApplicationBuilder接口的UseRouting和UseEndpoints扩展方法注册了EndpointRoutingMiddleware和EndpointMiddleware中间件。在调用UseEndpoints方法的时候,我们利用指定的Action<IEndpointRouteBuilder>委托对象调用了IEndpointRouteBuilder接口的MapControllers扩展方法完成了针对定义在Controller类型中所有Action方法的映射。
由于注册的中间件具有对其他服务的依赖,我们需要预先将这些服务注册到依赖注入框架中。依赖服务的注册通过调用IWebHostBuilder的ConfigureServices方法来完成,该方法的参数类型为Action<IServiceCollection>,添加的服务注册就保存在IServiceCollection接口表示的集合中。在上面的演示程序中,两个中间件依赖的服务是通过调用IServiceCollection接口的AddRouting和AddControllersWithViews方法进行注册的。
如下所示的HelloController是我们定义的Controller类型。按照约定,所有的Controller类型名称都应该以“Controller”字符作为后缀。与之前版本的ASP.NET MVC不同,ASP.NET Core MVC下的Controller类型并不要求强制继承某个基类。我们在HelloController中定义了一个唯一的Action方法SayHello,该方法直接返回一个内容为“Hello World”的字符串。
public class HelloController
{
[HttpGet("/hello")]
public string SayHello() => "Hello World.";
}
我们在Action方法SayHello上通过标注的HttpGetAttribute特性注册了一个模板为“/hello”的路由,意味着请求地址为“/hello”的GET请求最终会被路由到这个Action方法上,而该方法执行的结果将作为请求的响应内容。所以启动该程序后使用浏览器访问地址“http://localhost:5000/hello”,我们依然会得到如下图所示的输出结果。
二、引入视图
上面这个程序并没有涉及视图,所以算不上一个典型的MVC应用,接下来我们对它做进一步改造。为了让HelloController具有视图呈现的能力,我们让它派生于基类Controller。Action方法SayHello的返回类型被修改为IActionResult接口,它表示Action方法执行的结果。我们为该方法定义了一个表示姓名的参数name,通过HttpGetAttribute特性注册的路由模板(“/hello/{name}”)中具有与之对应的路由参数。换句话说,满足该路径模式的请求URL携带的姓名将自动绑定到该Action方法的name参数上。在SayHello方法中,我们利用ViewBag将代表姓名的name参数值传递给呈现的视图,该方法最终调用View方法返回当前Action方法对应的ViewResult对象。
public class HelloController : Controller
{
[HttpGet("/hello/{name}")]
public IActionResult SayHello(string name)
{
ViewBag.Name = name;
return View();
}
}
由于我们调用View方法时没有显式指定视图的名称,所以视图引擎会将当前Action的名称(“SayHello”)作为视图的名称。如果该视图还没有经过编译(部署时针对View的预编译,或者在这之前针对该View的动态编译),视图引擎将从若干候选的路径中读取对应的.cshtml 文件进行编译,其中首选的路径为“{ContentRoot}\Views\{ControllerName}\{ViewName}.cshtml”。为了迎合视图引擎定位视图文件的规则,我们需要将SayHello对应的视图文件(SayHello.cshtml)定义在目录“\Views\Hello\”下。
如下所示的就是SayHello.cshtml这个文件的内容,这是一个针对Razor引擎的视图文件。从文件的扩展名(.cshtml)我们看出可以这样的文件可以同时包含HTML标签和C#代码。总的来说,视图文件会在服务端生成最终在浏览器呈现出来的HTML,我们可以在这个文件中直接提供原样输出的HTML标签,也可以内嵌一段动态执行的C#代码。虽然Razor引擎对View文件的编写制定了严格的语法,但是我个人觉得没有必要在Razor语法上花太多的精力,因为Razor语法的目的就是让我们很“自然”地将动态C#代码和静态HTML标签结合起来,并最终生成一份完整的HTML文档,因此它的语法和普通的思维基本是一致。比如下面这个View最终会生成一个完整的HTML文档,其主体部分只有一个<p>标签。该标签的内容是动态的,因为包含利用ViewBag从Controller传进来的姓名。
<html>
<head>
<title>Hello World</title>
</head>
<body>
<p>Hello, @ViewBag.Name</p>
</body>
</html>
再次运行该程序后,我们利用浏览器访问地址“http://localhost:5000/hello/foobar”。由于请求地址与Action方法SayHello上的路由规则相匹配,所以路径携带的姓名(foobar)会绑定到该方法的name参数上,所以我们最终将在浏览器上得到如下图所示的输出结果。
三、使用Startup类型
任何一个ASP.NET Core应用在初始化的时候都会根据请求处理的需求注册对应的中间件。在前面演示的实例中,我们都是直接调用IWebHostBuilder的Configure扩展方法来注册所需的中间件,但是在大部分真实的开发场景中我们一般会将中间件以及依赖服务的注册定义在一个单独的类型中。按照约定,我们通常会将这个类型命名为Startup,比如我们演示实例中针对服务和中间件的注册就可以放在如下定义的这个Startup类中。
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services
.AddRouting()
.AddControllersWithViews(); public void Configure(IApplicationBuilder app) => app
.UseRouting()
.UseEndpoints(endpoints => endpoints.MapControllers());
}
如上面的代码片段所示,我们不需要让Startup类实现某个预定义的接口或者继承某个预定义基类,所采用的完全是一种基于“约定”的定义方式。随着对ASP.NET Core框架认识的加深,我们会发现这种“约定优于配置”的设计广泛地应用在整个框架之中。按照约定,服务注册和中间件注册分别实现在ConfigureServices和Configure方法中,它们的第一个参数类型分别为IServiceCollection和IApplicationBuilder接口。由于已经将两种核心的操作转移到了Startup类型中,所以我们需要注册该类型。Startup类型可以调用IWebHostBuilder接口的UseStartup<TStartup>扩展方法进行注册。
class Program
{
static void Main()
{
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.UseStartup<Startup>())
.Build()
.Run();
}
}
我们在前面的内容中对.NET Core、ASP.NET Core以及ASP.NET Core MVC应用的编程作了初步的体验,但是这仅仅限于我们熟悉的Windows平台。作为一个号称跨平台的开发框架,我们有必要在其他操作系统平台上体验一下.NET Core开发的乐趣。
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [上篇]
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Mac OS
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Linux
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Docker
[ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]的更多相关文章
- [转][ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]
由于ASP.NET Core框架在本质上就是由服务器和中间件构建的消息处理管道,所以在它上面构建的应用开发框架都是建立在某种类型的中间件上,整个ASP.NET Core MVC开发框架就是建立在用来实 ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [上篇]
微软在千禧年推出 .NET战略,并在两年后推出第一个版本的.NET Framework和IDE(Visual Studio.NET 2002,后来改名为Visual Studio),如果你是一个资深的 ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]
我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...
- [转][ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [上篇]
微软在千禧年推出 .NET战略,并在两年后推出第一个版本的.NET Framework和IDE(Visual Studio.NET 2002,后来改名为Visual Studio),如果你是一个资深的 ...
- [转][ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]
我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Docker
对于一个 .NET Core开发人员,你可能没有使用过Docker,但是你不可能没有听说过Docker.Docker是Github上最受欢迎的开源项目之一,它号称要成为所有云应用的基石,并把互联网升级 ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Linux
如果想体验Linux环境下开发.NET Core应用,我们有多种选择.一种就是在一台物理机上安装原生的Linux,我们可以根据自身的喜好选择某种Linux Distribution,目前来说像RHEL ...
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Mac OS
除了微软自家的Windows平台, .NET Core针对Mac OS以及各种Linux Distribution(RHEL.Ubuntu.Debian.Fedora.CentOS和SUSE等)都提供 ...
- 《ASP.NET Core 3框架揭秘》博文汇总
在过去一段时间内,写了一系列关于ASP.NET Core 3相关的文章,其中绝大部分来源于即将出版的<ASP.NET Core 3框架揭秘>(博文只能算是"初稿",与书 ...
随机推荐
- 来理解undefined 和 null 区别
之前虽然也知道这两个之间的区别,但是让我描述的话,感觉上还是说的不是很清楚.今天也详细看了一次这个知识点,现在来说说这两者间的区别. null: Null类型,代表“空值”,代表一个空对象指针,使用t ...
- linux进程管理常用命令
初始化进程在centos5,6,7中的发展: 在centos5中使用sysv init 是一个shell脚本,依靠依次执行脚本中的命令启动系统,只能串行执行. 在centos6中使用upstart,也 ...
- supervisor 安装配置详解
一.安装 源码安装 先下载最新的supervisor安装包:https://pypi.python.org/pypi/supervisor , 如: (python3命令为 pip install g ...
- scrapy的一个简单小项目
使用scrapy抓取目标url下所有的课程名和价格,并将数据保存为json格式url=http://www.tanzhouedu.com/mall/course/initAllCourse 观察网页并 ...
- nginx实现前后台分离部署
2.1 前后台分离部署 (一) 组网图 (二) 简要说明: 如标题所示,至于为什么要前后台分离部署,个人理解的原因有三 (一) 便于部署 前台代码由ngin ...
- 手写Promise A+ 规范
基于ES6语法手写promise A+ 规范,源码实现 class Promise { constructor(excutorCallBack) { this.status = 'pending'; ...
- 虚拟化--思杰citrix
目前虚拟化主要有vmware,微软,思杰 一:从硬件搭建开始 硬件需要问的几个问题: a.负载均衡.防火墙.路由器怎么配置? b.新增一块存储的话,怎么新增? 二:安装citrix xen serve ...
- PHP根据经纬度获取在范围坐标的数据
// 计算范围,可以做搜索用户 function GetRange($lat,$lon,$raidus){ //计算纬度 $degree = (24901 * 1609) / 360.0; $dpmL ...
- js4——字符转化
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 创建raid10(五块磁盘)
创建raid10(五块磁盘) Raid10(5块磁盘) 上一个bolg已经做了raid5(3 个raid. 2个备份),在此条件下继续以下步骤: 1.先将磁盘系统卸载 2.看系统挂载里是否还有md0 ...