ASP.NET Core - 快速指南


ASP.NET Core - 概述

ASP.NET Core 是 Microsoft 的新 Web 框架。它经过了彻底的重新设计,变得快速、灵活、现代,并且可以跨不同平台工作。展望未来,ASP.NET Core 是可用于通过 .NET 进行 Web 开发的框架。如果您在过去几年有过使用 MVC 或 Web API 的经验,您会注意到一些熟悉的功能。在本教程结束时,您将拥有开始使用 ASP.NET Core 并编写可以创建、编辑和查看数据库中的数据的应用程序所需的一切。

ASP.NET 简史

ASP.NET 多年来一直用于开发 Web 应用程序。从那时起,该框架经历了稳步的演进变化,最终引导我们推出了其最新的后代 ASP.NET Core 1.0。

  • ASP.NET Core 1.0 不是 ASP.NET 4.6 的延续。

  • 这是一个全新的框架,一个并行的项目,它与我们所知道的其他一切愉快地共存。

  • 它是当前 ASP.NET 4.6 框架的实际重写,但更小且模块化程度更高。

  • 有些人认为很多事情保持不变,但这并不完全正确。ASP.NET Core 1.0 是对 ASP.NET 格局的重大根本性改变。

什么是 ASP.NET Core

ASP.NET Core 是一个开源且云优化的 Web 框架,用于开发可在 Windows、Linux 和 Mac 上开发和运行的现代 Web 应用程序。它包括 MVC 框架,现在将 MVC 和 Web API 的功能组合到一个 Web 编程框架中。

  • ASP.NET Core 应用程序可以在 .NET Core 或完整的 .NET Framework 上运行。

  • 它的架构旨在为部署到云或在本地运行的应用程序提供优化的开发框架。

  • 它由模块化组件组成,开销最小,因此您可以在构建解决方案时保持灵活性。

  • 您可以在 Windows、Mac 和 Linux 上跨平台开发和运行 ASP.NET Core 应用程序。

ASP.NET Core 的优点

ASP.NET Core 具有以下优点 -

  • ASP.NET Core 进行了许多架构更改,从而形成了更加精简和模块化的框架。

  • ASP.NET Core 不再基于 System.Web.dll。它基于一组精细且精心设计的 NuGet 包。

  • 这允许您优化您的应用程序以仅包含您需要的 NuGet 包。

  • 较小的应用程序表面积的好处包括更严格的安全性、减少服务、提高性能和降低成本

使用 ASP.NET Core,您可以获得以下改进 -

  • 在 Windows、Mac 和 Linux 上构建和运行跨平台 ASP.NET 应用程序。

  • 基于 .NET Core 构建,支持真正的并行应用程序版本控制。

  • 简化现代 Web 开发的新工具。

  • 用于 Web UI 和 Web API 的单一对齐 Web 堆栈。

  • 基于云的环境配置。

  • 对依赖注入的内置支持。

  • 标签帮助程序使 Razor 标记在 HTML 中更加自然。

  • 能够在 IIS 上托管或在您自己的进程中自行托管。

ASP.NET Core - 环境设置

ASP.NET Core 是 ASP.NET 的重大重新设计。本主题介绍 ASP.NET Core 中的新概念并解释它们如何帮助您开发现代 Web 应用程序。

要在应用程序中使用 ASP.NET Core,必须在系统中安装以下内容 -

  • 微软视觉工作室 2015
  • Microsoft .NET Core 1.0.0 - VS 2015 工具预览 2

Microsoft 提供了 Visual Studio 的免费版本,其中还包含 SQL Server,可以从www.visualstudio.com/en-us/downloads/downloadvisual-studio-vs.aspx和 Microsoft .NET Core 1.0.0 - VS 2015下载工具预览 2 可以从 https://go.microsoft.com/fwlink/?LinkId=817245 下载

安装 Microsoft Visual Studio 2015

现在让我们了解一下安装所涉及的步骤

步骤 1 - 下载完成后,运行安装程序。将显示以下对话框。

对话框

步骤 2 - 单击安装按钮,如上面的屏幕截图所示。然后安装过程将开始。

安装按钮

步骤 3 - 安装过程成功完成后,您将看到以下对话框。

现在重启

步骤 4 - 关闭此对话框并根据需要重新启动计算机。

步骤 5 - 从“开始”菜单打开 Visual Studio。这将打开以下对话框,第一次需要一些时间(仅用于准备)。

视觉工作室

步骤 6 - 您现在将看到 Visual Studio 的主窗口。

主窗口 Visual Studio

步骤 7 - 安装 Visual Studio 后,关闭 Visual Studio 并启动 Microsoft .NET Core 1.0.0 - VS 2015 Tooling Preview 2。

微软.NET核心1.0.0

步骤 8 - 选中复选框并单击安装。

勾选并安装

步骤 9 - 安装完成后,您将看到以下消息。

安装成功

步骤 10 - 您现在已准备好使用 ASP.NET Core 启动应用程序。

ASP.NET Core - 新项目

在本章中,我们将讨论如何在 Visual Studio 中创建新项目。

安装 Visual Studio 2015 工具后,您可以从“文件” →“新建项目”菜单选项开始构建新的 ASP.NET Core 应用程序。

新项目菜单选项

在“新建项目”对话框中,您将看到以下三种不同的 Web 项目模板 -

  • ASP.NET Web 应用程序- 简单的 ASP.NET 应用程序模板。

  • ASP.NET Core Web 应用程序 (.NET Core) - 这将为您启动一个在 .NET Core 框架上运行的跨平台兼容项目。

  • ASP.NET Core Web 应用程序 (.NET Framework) - 这将启动一个在 Windows 上的标准 .NET Framework 上运行的新项目。

在左侧窗格中,选择模板 → Visual C# → Web,然后在中间窗格中选择 ASP.NET Core Web 应用程序 (.NET Core) 模板。我们将此应用程序命名为FirstAppDemo,并指定 ASP.NET Core 项目的位置,然后单击“确定”。

第一个应用程序演示

在上面的对话框中,您可以从可用的 ASP.NET Core 模板中为 ASP.NET 应用程序选择特定模板。

ASP.NET Core 模板当前包含三种不同的模板。其中,Web 应用程序模板将帮助您在文件系统上布置大量文件。这还允许您立即使用 ASP.NET MVC。

在这里,我们将从一个空模板开始。这将帮助我们从头开始构建它。让我们选择空模板,关闭云中的主机,然后单击确定。

网页应用程序模板

Visual Studio 现在将在一段时间内启动该项目。在“解决方案资源管理器”窗口中,您将看到该项目中的所有文件。

让我们运行这个应用程序,您可以通过按 Ctrl+F5 或转到“调试”菜单来执行此操作。进入“调试”菜单后,选择“启动而不调试”

无需调试即可启动

该应用程序只能显示Hello World!它在localhost:57741上运行。在窗口系统托盘中,您还可以看到 IIS Express 正在运行。

本地主机 57741

该网站的名称是FirstAppDemo。如果您一直使用该框架的早期版本使用 ASP.NET 进行编程,那么您与 Visual Studio 交互的方式以及 Visual Studio 使用 IIS Express 托管应用程序的方式,所有这些方面都会很熟悉。

ASP.NET Core - 项目布局

在本章中,我们将讨论 ASP.NET Core 项目如何出现在文件系统上以及不同的文件和目录如何协同工作。

让我们打开上一章中创建的FirstAppDemo项目。

第一个演示应用程序

在“解决方案资源管理器”窗口中,右键单击“解决方案”节点,然后选择“在文件资源管理器中打开文件夹”

右键单击解决方案

您现在将看到根目录中包含两个文件:FirstAppDemo.slnglobal.json

全局Json

FirstAppDemo.sln是一个解决方案文件。默认情况下,Visual Studio 多年来一直使用此扩展,如果您想在 Studio 中打开应用程序并对其进行处理,可以双击该文件。

还有一个global.json文件。让我们在 Visual Studio 中打开该文件。

第一个应用程序演示

在该文件中,项目的设置很重要。此项目设置告诉 ASP.NET 在哪里查找源代码以及哪些文件夹包含您的项目。

有两个可能的文件夹“ src ”用于源和一个“ test ”文件夹。除非您的项目和源代码位于这两个文件夹之一,否则代码将无法构建。如果需要,您可以更改这些设置。

Windows 资源管理器在磁盘上有“src”文件夹。您没有测试文件夹。在测试文件夹中,您可以放置​​单元测试项目。让我们双击“src”文件夹。

SRC文件夹

您可以看到 FirstAppDemo 项目和 Web 应用程序。现在,双击该文件夹。

Web应用程序

这些是应用程序的源代码文件,您还可以在“解决方案资源管理器”窗口中看到此文件夹结构。这是因为在当前版本的 ASP.NET Core 中,文件系统决定了项目中的内容。

如果将新文件添加到磁盘,该文件将被添加到项目中。如果删除文件,该文件将从项目中删除。一切都保持同步,这与以前版本的 ASP.NET Core 略有不同,其中项目文件(*.cs proj 文件)包含项目中所有内容的清单。

当文件更改或新文件出现时,ASP.NET Core 还会编译您的应用程序。

例子

让我们通过在文本编辑器中打开Startup.cs文件来查看一个简单的示例。

例子

正是这行代码响应对应用程序的每个 HTTP 请求,并且仅响应 Hello World!

让我们通过说“ Hello World!”来更改上面屏幕截图中的字符串。此 ASP.NET Core 应用程序”如以下程序所示。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 

using Microsoft.AspNetCore.Builder; 
using Microsoft.AspNetCore.Hosting; 
using Microsoft.AspNetCore.Http; 

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;  

namespace FirstAppDemo {
   public class Startup { 
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime. 
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app, 
         IHostingEnvironment env, ILoggerFactory loggerFactory) { 
         loggerFactory.AddConsole();  
         
         if (env.IsDevelopment()){ 
            app.UseDeveloperExceptionPage(); 
         }  
         app.Run(async (context) => { 
            await context.Response.WriteAsync(
               "Hello World! This ASP.NET Core Application");
         });
      } 
   } 
} 

按 Ctrl + S 将此文件保存在文本编辑器中,然后返回到 Web 浏览器并刷新应用程序。

保存并打开浏览器

您现在可以看到您的更改已反映在浏览器中。

  • 这是因为 ASP.NET 将监视文件系统并在文件更改时自动重新编译应用程序。您不需要在 Visual Studio 中显式构建应用程序。

  • 事实上,您可以使用完全不同的编辑器,例如 Visual Studio Code。

  • 使用 Visual Studio,您所需要做的就是通过在不使用调试器的情况下运行来启动 Web 服务器。您还可以按 Ctrl + F5,并可以编辑文件、保存文件,只需刷新浏览器即可查看更改。

  • 对于使用 C# 等编译语言构建 Web 应用程序来说,这是一个很好的工作流程。

ASP.NET Core - Project.Json

在本章中,我们将讨论project.json文件。该文件使用 JavaScript 对象表示法来存储配置信息,并且该文件才是 .NET 应用程序的真正核心。如果没有此文件,您就不会有 ASP.NET Core 项目。在这里,我们将讨论该文件的一些最重要的功能。让我们双击project.json文件。

双击 JSon 项目

目前,project.json 文件中的默认代码实现如下 -

{
   "dependencies": {
      "Microsoft.NETCore.App": {
         "version": "1.0.0",
         "type": "platform"
      },
      "Microsoft.AspNetCore.Diagnostics": "1.0.0",
      "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
      "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
      "Microsoft.Extensions.Logging.Console": "1.0.0"
   },
   "tools": {
      "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
   },
   "frameworks": {
      "netcoreapp1.0": {
         "imports": ["dotnet5.6", "portable-net45+win8"]
      }
   },
   "buildOptions": {
      "emitEntryPoint": true,
      "preserveCompilationContext": true
   },
   "runtimeOptions": {
      "configProperties": {
         "System.GC.Server": true
      }
   },
   "publishOptions": {
      "include": ["wwwroot", "web.config" ]
   },
   "scripts": {
      "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath%
         --framework %publish:FullTargetFramework%" ]
   }
}

正如我们所看到的,我们在该文件的顶部有版本信息。这是您的应用程序在构建时将使用的版本号。

  • 版本是1.0.0,但是这个文件最重要的部分是依赖项。

  • 如果您的应用程序要执行任何有用的工作,那么您将需要库和框架来执行该工作,例如在数据库中存储和检索数据或呈现复杂的 HTML。

  • 在此版本的 ASP.NET Core 中,依赖项全部通过 NuGet 包管理器进行管理。

  • NuGet 在 .NET 领域已经存在了几年,但现在管理所有依赖项的主要方法是使用包装为 NuGet 包的库和框架。

  • 应用程序所需的所有顶级 NuGet 包都将存储在此 project.json 文件中。

"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0

您可以看到我们在此文件中有一些依赖项,并且确切的依赖项可能会在 ASP.NET 的最终版本中发生更改。当您想要添加新的依赖项(例如 ASP.NET MVC 框架)时,您可以轻松地在该 project.json 文件中键入内容,并且您还将获得一些IntelliSense帮助,其中不仅包括包名称,还包括版本号,如下所示下面的截图。

智能感知

您还可以通过右键单击“解决方案资源管理器”中的“引用”,然后选择“管理 NuGet 包”来使用 UI。您现在可以看到当前安装的软件包。

已安装的软件包

这些包与您的project.json 文件中的包相同,您还可以转到浏览器并添加其他包,包括预发布的包,比如说安装到该项目中的MVC 框架。

MVC框架

如果您立即使用“安装”按钮安装此包,则此包将存储在 project.json 中。Frameworks 部分是project.json 的另一个重要部分,此部分告诉 ASP.NET 您的应用程序可以使用哪些 .NET 框架。

“构架”: {
   “netcoreapp1.0”:{
      “进口”:[
         “dotnet5.6”,
         “便携式-net45+win8”
      ]
   }
},

在这种情况下,您将看到“ netcoreapp1.0 ”是项目中使用的框架,您还可以包含安装 Visual Studio 时安装的完整 .NET Framework。

  • 许多版本的 Windows 操作系统中都包含相同的 .NET Framework。

  • .NET Framework 已经存在了 15 年,它包含的框架可以执行从 Web 编程到桌面编程的所有操作。

  • 它是一个巨大的框架,只能在 Windows 上运行。

  • “netcoreapp1.0”是.NET Core 框架。它是一个跨平台框架,可以工作在各种平台上,不仅是Windows,还可以工作在OS X和Linux上。

  • 该框架的功能比完整的 .NET 框架少,但它确实具有 ASP.NET Core Web 开发所需的所有功能。

ASP.NET Core - 配置

在本章中,我们将讨论与 ASP.NET Core 项目相关的配置。在解决方案资源管理器中,您将看到 Startup.cs 文件。如果您使用过 ASP.NET Core 的早期版本,您可能会期望看到一个 global.asax 文件,您可以在该文件中编写在 Web 应用程序启动期间执行的代码。

  • 您还希望看到一个 web.config 文件,其中包含应用程序执行所需的所有配置参数。

  • 在 ASP.NET Core 中,这些文件都消失了,而是从 Startup.cs 加载配置和启动代码。

  • 文件中有一个 Startup 类,在这个类中您可以配置您的应用程序,甚至配置您的配置源。

以下是Startup.cs 文件中的默认实现。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 

using Microsoft.AspNetCore.Builder; 
using Microsoft.AspNetCore.Hosting; 
using Microsoft.AspNetCore.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Logging;  

namespace FirstAppDemo { 
   public class Startup { 
      // This method gets called by the runtime.
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime. Use this method to configure 
      // the HTTP request pipeline.
      public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
         ILoggerFactory loggerFactory) { 
         loggerFactory.AddConsole();  
         
         if (env.IsDevelopment()) { 
            app.UseDeveloperExceptionPage(); 
         }  
         app.Run(async (context) => { 
            await context.Response.WriteAsync("Hello World!"); 
         }); 
      } 
   } 
}

在 Startup 类中,有两种方法将完成我们的大部分工作。该类的Configure 方法是您构建HTTP 处理管道的地方。

  • 这定义了您的应用程序如何响应请求。目前这个应用程序只能说Hello World!如果我们希望应用程序有不同的Behave,我们需要通过在此配置方法中添加额外的代码来更改管道。

  • 例如,如果我们想要提供静态文件(例如index.html 文件),我们需要向Configure 方法添加一些代码。

  • 您还可以有一个错误页面或将请求路由到 ASP.NET MVC 控制器;这两种情况都需要在此配置方法中执行一些工作。

  • 在Startup类中,您还将看到ConfigureServices()方法。这可以帮助您为应用程序配置组件。

现在,我们为每个响应都有一个硬编码字符串 - Hello World!细绳。我们不想对字符串进行硬编码,而是希望从某个知道我们要显示的文本的组件加载该字符串。

  • 这个其他组件可能会从数据库、Web 服务或 JSON 文件加载该文本,无论它到底在哪里。

  • 我们将设置一个场景,这样我们就没有这个硬编码的字符串。

在解决方案资源管理器中,右键单击项目节点并选择“添加”→“新项目”

添加第一项

在左侧窗格中,选择“已安装”→“代码”,然后在中间窗格中选择“JSON 文件”。将此文件命名为AppSettings.json,然后单击“添加”按钮,如上面的屏幕截图所示。

安装的代码

我们还可以让我们的程序从文件中读取文本,而不是使用 Hello World! Startup.cs 中的字符串。让我们在AppSettings.json 文件中添加以下代码。

{ 
   "message": "Hello, World! this message is from configuration file..." 
}

现在我们需要从 Startup.cs 文件访问此消息。以下是Startup.cs文件的实现,它将从 JSON 文件中读取上述消息。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder()   
            .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }  
      
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) {
         app.UseIISPlatformHandler();  
         app.Run(async (context) => { 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         });  
      }  
        
      // Entry point for the application. 
      public static void Main(string[] args) =7gt; WebApplication.Run<Startup>(args); 
   } 
}

现在让我们运行该应用程序。运行该应用程序后,它将产生以下输出。

运行应用程序

ASP.NET Core - 中间件

在本章中,我们将了解如何设置中间件。ASP.NET Core 中的中间件控制我们的应用程序如何响应 HTTP 请求。它还可以控制我们的应用程序在出现错误时的外观,并且它是我们如何验证和授权用户执行特定操作的关键部分。

  • 中间件是组装到应用程序管道中以处理请求和响应的软件组件。

  • 每个组件选择是否将请求传递给管道中的下一个组件,并且可以在调用管道中的下一个组件之前和之后执行某些操作。

  • 请求委托用于构建请求管道。请求委托处理每个 HTTP 请求。

  • ASP.NET Core 中的每个中间件都是一个对象,并且每个中间件都有非常具体、集中且有限的作用。

  • 最终,我们需要许多中间件才能使应用程序正常运行。

现在假设我们想要将每个请求的信息记录到我们的应用程序中。

  • 在这种情况下,我们可能安装到应用程序中的第一个中间件是日志记录组件。

  • 该记录器可以看到有关传入请求的所有信息,但记录器很可能只是记录一些信息,然后将此请求传递给下一个中间件。

中间件
  • 中间件是该处理管道中存在的一系列组件。

  • 我们安装到应用程序中的下一个中间件是授权者。

  • 授权者可能会在 HTTP 标头中查找特定的 cookie 或访问令牌。

  • 如果授权者找到令牌,则允许请求继续进行。如果没有,授权者本身可能会使用 HTTP 错误代码或重定向代码来响应请求,以将用户发送到登录页面。

  • 但是,否则,授权者会将请求传递给下一个中间件,即路由器。

  • 路由器会查看 URL 并确定您的下一步操作。

  • 路由器会在应用程序中查找要响应的内容,如果路由器没有找到要响应的内容,则路由器本身可能会返回404 Not Found 错误

例子

现在让我们通过一个简单的例子来更多地了解中间件。我们使用Startup 类的 Configure 方法在 ASP.NET 中设置中间件。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() 
            .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }  
       
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         
         app.Run(async (context) => { 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         });  
      }  
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
   } 
} 

Configure()方法中,我们将调用IApplicationBuilder接口上的扩展方法来添加中间件。

默认情况下,新的空项目中有两个中间件 -

  • IIS平台处理程序
  • 使用 app.Run 注册的中间件

IIS平台处理程序

IISPlatformHandler允许我们使用 Windows 身份验证。它将查看每个传入请求并查看是否有与该请求关联的任何 Windows 身份信息,然后调用下一个中间件。

使用 app.Run 注册的中间件

在本例中,下一个中间件是通过app.Run注册的中间件。Run 方法允许我们传入另一个方法,我们可以用它来处理每个响应。Run 并不是您经常看到的东西,它是我们所说的终端中间件。

您在 Run 中注册的中间件永远不会有机会调用另一个中间件,它所做的只是接收请求,然后必须产生某种响应。

您还可以访问 Response 对象,并且可以使用 Response 对象执行的操作之一是写入字符串。

如果您想在 app.Run 之后注册另一个中间件,那么该中间件将永远不会被调用,因为 Run 是一个终端中间件。它永远不会调用下一个中间件。

如何添加另一个中间件

让我们继续执行以下步骤来添加另一个中间件 -

步骤 1 - 要添加另一个中间件,请右键单击项目并选择管理 NuGet 包。

步骤 2 - 搜索Microsoft.aspnet.diagnostics,它实际上是 ASP.NET Core 中间件,用于异常处理、异常显示页面和诊断信息。这个特定的包包含我们可以使用的许多不同的中间件。

微软 AspNet 诊断

步骤 3 - 如果您的项目中未安装该软件包,请安装该软件包。

步骤 4 - 现在让我们转到Configure()方法并调用app.UseWelcomePage中间件。

// This method gets called by the runtime.  
// Use this method to configure the HTTP request pipeline. 
public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler(); 
   app.UseWelcomePage();  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
}

步骤 5 - 运行您的应用程序,您将看到以下欢迎屏幕。

欢迎屏幕

此欢迎屏幕可能没有那么有用。

步骤 6 - 让我们尝试一些可能更有用的东西。我们将使用 RuntimeInfoPage 来代替欢迎页面

// This method gets called by the runtime.  
// Use this method to configure the HTTP request pipeline. 
public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler(); 
   app.UseRuntimeInfoPage();  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
}

步骤 7 - 保存Startup.cs页面并刷新浏览器,您将看到以下页面。

启动CS

RuntimeInfoPage是一个中间件,仅响应针对特定 URL 传入的请求。如果传入的请求与该 URL 不匹配,则该中间件只会让请求传递到下一个中​​间件。请求会经过IISPlatformHandler中间件,然后转到UseRuntimeInfoPage中间件。它不会创建响应,因此它将转到我们的应用程序。运行并显示字符串。

步骤 8 - 让我们在 URL 末尾添加“/ runtimeinfo ”。您现在将看到由该运行时信息页面中间件生成的页面。

运行时信息

现在,您将看到一个响应,其中提供了有关运行时环境的一些信息,例如操作系统、运行时版本、体系结构、类型以及您正在使用的所有包等。

ASP.NET Core - 异常

在本章中,我们将讨论异常和错误处理。当 ASP.NET Core 应用程序发生错误时,您可以通过多种方式处理它们。让我们看看可通过诊断包使用的附加中间件。这个中间件将帮助我们处理错误。

为了模拟错误,让我们转到app.Run并看看如果我们每次访问这个中间件时都抛出异常,应用程序的Behave如何。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() 
            .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }  
        
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime. 
      // Use this method to configure the HTTP request pipeline.
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         app.UseRuntimeInfoPage();  
         
         app.Run(async (context) => { 
            throw new System.Exception("Throw Exception"); 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         });  
      }  
        
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
   }   
} 

它只会抛出一个带有非常通用消息的异常。保存Startup.cs页面并运行您的应用程序。

通用消息

您将看到我们无法加载此资源。存在 HTTP 500 错误、内部服务器错误,这没有多大帮助。获得一些异常信息可能会很好。

让我们添加另一块中间件,即UseDeveloperExceptionPage

// This method gets called by the runtime.  
// Use this method to configure the HTTP request pipeline. 
public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler();  
   app.UseDeveloperExceptionPage(); 
   app.UseRuntimeInfoPage();  
   
   app.Run(async (context) => { 
      throw new System.Exception("Throw Exception"); 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
}
  • 这个中间件与其他中间件有点不同,其他中间件通常查看传入的请求并对该请求做出一些决定。

  • UseDeveloperExceptionPage 并不关心传入的请求,而是关心管道中稍后发生的事情。

  • 它只会调用下一个中间件,但随后它将等待查看管道中稍后的任何内容是否生成异常,如果有异常,该中间件将为您提供一个错误页面,其中包含一些内容有关该异常的附加信息。

现在让我们再次运行该应用程序。它将产生如下屏幕截图所示的输出。

内部服务器错误

现在,如果开发中出现错误,您将看到一些您所期望的信息。您还将获得堆栈跟踪,并且可以看到 Startup.cs 的第 37 行引发了未处理的异常。

您还可以查看原始异常详细信息,所有这些信息对于开发人员都非常有用。事实上,我们可能只想在开发人员运行应用程序时显示这些信息。

ASP.NET Core - 静态文件

在本章中,我们将学习如何使用文件。几乎每个 Web 应用程序都需要的一个重要功能是能够从文件系统提供文件(静态文件)。

  • 文件系统上的静态文件(例如 JavaScript 文件、图像、CSS 文件)是 ASP.NET Core 应用程序可以直接向客户端提供服务的资产。

  • 静态文件通常位于 Web 根 (wwwroot) 文件夹中。

  • 默认情况下,这是我们可以直接从文件系统提供文件的唯一位置。

例子

现在让我们举一个简单的例子,我们将了解如何在应用程序中提供这些文件。

在这里,我们想要向 FirstAppDemo 应用程序添加一个简单的 HTML 文件,并且该 HTML 文件必须进入 Web 根 (wwwroot) 文件夹。右键单击解决方案资源管理器中的 wwwroot 文件夹,然后选择添加 → 新项目

添加新项目

在中间窗格中,选择HTML 页面并将其命名为index.html,然后单击“添加”按钮。

网页

您将看到一个简单的index.html文件。让我们添加一些简单的文本和标题,如下所示。

<!DOCTYPE html> 
<html> 
   <head> 
      <meta charset="utf-8" /> 
      <title>Welcome to ASP.NET Core</title> 
   </head> 

   <body> 
      Hello, Wolrd! this message is from our first static HTML file.  
   </body> 
</html>

当您运行应用程序并在浏览器中转到index.html时,您将看到app.Run中间件抛出异常,因为我们的应用程序中当前没有任何内容。

索引HTML

没有中间件会在文件系统上寻找任何文件来提供服务。要解决此问题,请在“解决方案资源管理器”中右键单击您的项目并选择“管理 NuGet 包”,转到 NuGet 包管理器

Nuget 包

搜索Microsoft.AspNet.StaticFiles将找到静态文件中间件。让我们安装这个 nuget 包,现在我们应该有其他方法可以用来在配置方法中注册中间件。

让我们在Configure方法中添加UseStaticFiles,如下面的程序所示。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() 
            .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }  
      
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
      }  
      
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         app.UseDeveloperExceptionPage(); app.UseRuntimeInfoPage(); 
         app.UseStaticFiles(); 
         
         app.Run(async (context) => { 
            throw new System.Exception("Throw Exception"); 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         }); 
      }  
        
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
   } 
} 

除非您覆盖选项并传入一些不同的配置参数,否则静态文件对于给定的请求所做的就是查看请求路径。然后将该请求路径与文件系统以及文件系统上的内容进行比较。

  • 如果静态文件看到它可以使用的文件,它将提供该文件而不调用下一个中间件。

  • 如果没有找到匹配的文件,那么它将继续处理下一个中间件。

让我们保存Startup.cs文件并刷新您的浏览器。

启动.CS文件

您现在可以看到index.html 文件。您在 wwwroot 内的任何位置放置的任何内容 - 任何 JavaScript 文件、CSS 文件或 HTML 文件,您都可以提供它们。

  • 现在,如果您希望index.html成为您的默认文件,这是IIS一直具有的功能。

  • 您始终可以向 IIS 提供要查找的默认文件列表。如果有人访问目录的根目录,或者在本例中访问网站的根目录,并且 IIS 发现名为 index.html 的内容,它就会自动提供该文件。

  • 现在让我们开始做一些改变。首先,我们需要删除强制错误,然后添加另一个中间件,即UseDefaultFiles。下面是Configure方法的实现。

// This method gets called by the runtime.  
// Use this method to configure the HTTP request pipeline. 
public void Configure(IApplicationBuilder app)  { 
   app.UseIISPlatformHandler();  
   app.UseDeveloperExceptionPage(); 
   
   app.UseRuntimeInfoPage();  
   app.UseDefaultFiles(); 
   app.UseStaticFiles();  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
}
  • 该中间件将查看传入的请求,并查看它是否针对目录的根目录以及是否有任何匹配的默认文件。

  • 您可以覆盖该中间件的选项,以告诉它要查找的默认文件是什么,但 Index.html 默认情况下是默认文件之一。

让我们保存Startup.cs文件并在浏览器中转到 Web 应用程序的根目录。

网络应用程序浏览器

您现在可以看到index.html 是您的默认文件。安装中间件的顺序很重要,因为如果在 UseStaticFiles 之后使用 UseDefaultFiles,则不会得到相同的结果。

如果要使用 UseDefaultFiles 和 UseStaticFiles,您可能还需要 Microsoft.aspnet.staticfiles NuGet 包中的另一个中间件,即 FileServer中间件。这本质上包括按正确顺序排列的默认文件和静态文件。

// This method gets called by the runtime.  
// Use this method to configure the HTTP request pipeline. 
public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler();  
   app.UseDeveloperExceptionPage(); 
   
   app.UseRuntimeInfoPage();  
   app. UseFileServer();  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   }); 
}

让我们再次保存Startup.cs文件。刷新浏览器后,您将看到与以下屏幕截图所示相同的结果。

相同的结果

ASP.NET Core - 设置 MVC

在本章中,我们将在 FirstAppDemo 应用程序中设置 MVC 框架。我们将继续在 ASP.NET Core(更具体地说是 ASP.NET Core MVC 框架)之上构建 Web 应用程序。从技术上讲,我们可以仅使用中间件构建整个应用程序,但 ASP.NET Core MVC 为我们提供了可用于轻松创建 HTML 页面和基于 HTTP 的 API 的功能。

要在我们的空项目中设置 MVC 框架,请按照以下步骤操作 -

  • 安装Microsoft.AspNet.Mvc包,它使我们能够访问框架提供的程序集和类。

  • 安装包后,我们需要注册 ASP.NET MVC 在运行时所需的所有服务。我们将在ConfigureServices方法中执行此操作。

  • 最后,我们需要添加 ASP.NET MVC 接收请求的中间件。本质上,这个中间件接受一个 HTTP 请求,并尝试将该请求定向到我们将编写的 C# 类。

步骤 1 - 让我们右键单击“管理 NuGet 包”进入 NuGet 包管理器。安装 Microsoft.AspNet.Mvc 包,它使我们能够访问框架提供的程序集和类。

微软.AspNet.MVC

步骤 2 - 安装 Microsoft.AspNet.Mvc 包后,我们需要注册 ASP.NET Core MVC 在运行时所需的所有服务。我们将使用ConfigureServices 方法来完成此操作。我们还将添加一个简单的控制器,我们将看到该控制器的一些输出。

让我们向该项目添加一个新文件夹并将其命名为Controllers。在此文件夹中,我们可以放置多个控制器,如下所示的解决方案资源管理器。

控制器

现在右键单击 Controllers 文件夹并选择Add → Class菜单选项。

添加班级

步骤 3 - 这里我们要添加一个简单的C#类,并调用该类HomeController,然后单击“添加”按钮,如上面的屏幕截图所示。

家庭控制器

这将是我们的默认页面。

步骤 4 - 让我们定义一个返回字符串的公共方法并调用该方法 Index,如以下程序所示。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks;  

namespace FirstAppdemo.Controllers { 
   public class HomeController { 
      public string Index() { 
         return "Hello, World! this message is from Home Controller..."; 
      } 
   } 
}

步骤 5 - 当您转到网站的根目录时,您想查看控制器响应。截至目前,我们将提供我们的index.html 文件。

控制器响应

让我们进入网站的根目录并删除index.html。我们希望控制器而不是index.html文件进行响应。

步骤 6 - 现在转到 Startup 类中的 Configure 方法并添加UseMvcWithDefaultRoute中间件。

UseMvc 默认路由

步骤 7 - 现在刷新网站根目录下的应用程序。

刷新应用程序

您将遇到 500 错误。该错误表明框架无法找到所需的 ASP.NET Core MVC 服务。

ASP.NET Core 框架本身由不同的小组件组成,这些组件的职责非常集中。

例如,有一个组件必须定位并实例化控制器。

该组件需要位于 ASP.NET Core MVC 的服务集合中才能正常运行。

步骤8 - 除了添加NuGet包和中间件之外,我们还需要在ConfigureServices中添加AddMvc服务。这是 Startup 类的完整实现。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; }
      
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
         services.AddMvc(); 
      }
      
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         
         app.UseDeveloperExceptionPage(); 
         app.UseRuntimeInfoPage();  
         
         app.UseFileServer(); 
         app.UseMvcWithDefaultRoute();  
         
         app.Run(async (context) => { 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         });
      } 
      
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
   }  
}            

步骤 9 - 保存Startup.cs文件并转到浏览器并刷新它。您现在将收到来自我们的家庭控制器的响应。

Startup.Cs HomeController

ASP.NET Core - MVC 设计模式

MVC(模型-视图-控制器)设计模式实际上已经存在了几十年,并且已在许多不同的技术中使用,从 Smalltalk 到 C++ 再到 Java,现在在 C# 和 .NET 中作为设计构建用户界面时使用的模式。

  • MVC 设计模式是一种流行的软件应用程序用户界面层设计模式。

  • 在较大的应用程序中,您通常将模型-视图-控制器 UI 层与应用程序中的其他设计模式(例如数据访问模式和消息传递模式)结合起来。

  • 这些将共同构建完整的应用程序堆栈。

MVC 将应用程序的用户界面(UI)分为以下三个部分 -

  • 模型- 一组描述您正在使用的数据以及业务逻辑的类。

  • 视图- 定义应用程序的 UI 将如何显示。它是一个纯 HTML,决定了 UI 的外观。

  • 控制器- 一组处理用户通信、整体应用程序流程和特定于应用程序的逻辑的类。

MVC 背后的理念

现在让我们了解 MVC 背后的想法。

  • 这个想法是,您将有一个称为视图的组件,它单独负责呈现此用户界面,无论它应该是 HTML 还是实际上应该是桌面应用程序上的 UI 小部件。

  • 视图与模型对话,该模型包含视图需要显示的所有数据。

  • 在 Web 应用程序中,视图可能根本没有任何与其关联的代码。

  • 它可能只有 HTML,然后是一些表达式,说明从模型中获取数据片段并将它们插入到您在视图中构建的 HTML 模板内的正确位置。

多维控制器
  • 控制器组织一切。当 MVC 应用程序收到 HTTP 请求时,该请求将被路由到控制器,然后由控制器与数据库、文件系统或模型进行通信。

在 MVC 中,控制器接收到 HTTP 请求,控制器必须弄清楚如何将信息组合在一起以响应此请求。也许用户正在将浏览器定向到应用程序的 /books URL。因此控制器需要将这些信息组合在一起来显示图书列表。在这种情况下,控制器将构建一个模型。

MVC模型
  • 该模型对 HTTP 请求或控制器一无所知。

  • 该模型仅负责保存用户想要查看的书籍信息,以及与该书籍列表相关的任何逻辑。

  • 该模型只是我们可以使用的另一个 C# 类,如果您有一个复杂的模型,您可能会有多个类。

  • 一旦模型组合在一起,控制器就可以选择一个视图来渲染模型。

  • 视图将获取模型中的信息,例如所有书籍和每本书的标题等,并将使用该信息构建 HTML 页面。

  • 然后,该 HTML 在 HTTP 响应中发送回客户端,整个 HTTP 请求和响应事务就完成了。

这些是 MVC 设计模式的基础知识,该模式背后的思想是保持关注点分离。因此控制器只负责接受请求并构建模型。它是将我们需要的逻辑和数据携带到视图中的模型。那么视图只负责将该模型转换为 HTML。

ASP.NET Core - 路由

在 MVC 框架中,我们有三个组件,每个组件都专注于工作的特定部分。为了让这一切发挥作用,我们需要找到一种方法将这些 HTTP 请求发送到正确的控制器。在 ASP.NET Core MVC 中,此过程称为路由。路由是将 HTTP 请求定向到控制器的过程。

现在让我们了解如何将请求路由到不同的控制器。

  • ASP.NET Core 中间件需要一种方法来确定给定的 HTTP 请求是否应转到控制器进行处理。

  • MVC 中间件将根据 URL 和我们提供的一些配置信息做出此决定。在本章中,我们将在添加 MVC 中间件时在 Startup.cs 中定义此配置信息,或者您可以说路由信息。

  • 这种方法通常称为基于约定的路由。以下是传统路由的代码片段。

routeBuilder.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}"); 
  • 在这种方法中,我们定义模板来告诉 MVC 如何查看 URL 并查找控制器名称和操作名称,其中控制器是 C# 类,操作是该类的公共方法。

在上一章中,我们在应用程序中创建了一个控制器(HomeController),它是一个 C# 类,不需要从基类派生或实现接口或具有任何特殊属性。它是一个普通的 C# 类,名称为 HomeController,并且包含返回字符串的 Index 方法。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks;  

namespace FirstAppdemo.Controllers { 
   public class HomeController { 
      public string Index() { 
         return "Hello, World! this message is from Home Controller..."; 
      } 
   }
}     

在这里,我们将重点关注到控制器的路由。我们还将尝试了解路由的工作原理。

现在让我们返回到Startup 类,我们在该类中将 MVC 中间件配置到应用程序中。在Configure方法中,我们使用了UseMvcWithDefaultRoute方法。

public void Configure(IApplicationBuilder app) { 
   app.UseIISPlatformHandler();  
   
   app.UseDeveloperExceptionPage(); 
   app.UseRuntimeInfoPage();  
   
   app.UseFileServer(); 
   app.UseMvcWithDefaultRoute();  
   
   app.Run(async (context) => { 
      var msg = Configuration["message"]; 
      await context.Response.WriteAsync(msg); 
   });  
}

这给了我们一个默认的路由规则,允许我们访问HomeController。我们不使用UseMvcWithDefaultRoute ,而是使用UseMvc ,然后使用命名方法ConfigureRoute配置路由。以下是Startup.cs文件的实现。

using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Hosting; 
using Microsoft.AspNet.Http; 

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Configuration; 
using Microsoft.AspNet.Routing; 
using System;  

namespace FirstAppDemo { 
   public class Startup { 
      public Startup() { 
         var builder = new ConfigurationBuilder() .AddJsonFile("AppSettings.json"); 
         Configuration = builder.Build(); 
      }  
      public IConfiguration Configuration { get; set; } 
      
      // This method gets called by the runtime. 
      // Use this method to add services to the container. 
      // For more information on how to configure your application, 
      // visit http://go.microsoft.com/fwlink/?LinkID=398940 
      public void ConfigureServices(IServiceCollection services) { 
         services.AddMvc(); 
      }  
        
      // This method gets called by the runtime.  
      // Use this method to configure the HTTP request pipeline. 
      public void Configure(IApplicationBuilder app) { 
         app.UseIISPlatformHandler();  
         
         app.UseDeveloperExceptionPage(); 
         app.UseRuntimeInfoPage();  
         
         app.UseFileServer(); 
         app.UseMvc(ConfigureRoute);  
         
         app.Run(async (context) => { 
            var msg = Configuration["message"]; 
            await context.Response.WriteAsync(msg); 
         });
      }  
      private void ConfigureRoute(IRouteBuilder routeBuilder) { 
         //Home/Index 
         routeBuilder.MapRoute("Default", "{controller = Home}/{action = Index}/{id?}");
      }  
        
      // Entry point for the application. 
      public static void Main(string[] args) => WebApplication.Run<Startup>(args);
   } 
}  

ConfigureRoute方法中,你可以配置你的路由;您可以看到该方法必须采用 IRouteBuilder 类型的参数。路由的目标是描述 ASP.NET Core MVC 将用于处理 HTTP 请求并找到可以响应该请求的控制器的规则。

  • 您可以拥有一个可以将请求映射到不同控制器的路由。

  • 我们可以告诉routeBuilder我们要映射一条新路由,其名称为“Default”,然后提供最重要的路由信息​​,即模板。

  • 该模板是一个字符串,它将向 ASP.NET Core MVC 描述如何分解 URL。

  • 在上一个示例中,我们添加了一个 HomeController,因此您还可以请求以下任何 URL,它们也将被定向到 HomeController 上的 Index 操作。

    • http://本地主机:49940
    • http://localhost:49940/Home
    • http://localhost:49940/Home/索引
  • 当浏览器请求http://mysite/ 或 http://mysite/Home时,它​​会从 HomeController 的 Index 方法获取输出。

  • 您也可以通过更改浏览器中的 URL 来尝试此操作。在此示例中,它是http://localhost:49940/,但端口可能不同。

  • 如果将 /Home 或 /Home/Index 附加到 URL 并按 Enter 按钮,您将看到相同的结果。

  • ID末尾的问号表示该参数是可选的。换句话说,ASP.NET Core MVC 不必在这里看到某种 ID,它可能是数字、字符串或 GUID。

让我们在浏览器中运行该应用程序。应用程序运行后,您将看到以下输出。

输出

您可以看到 app.Run 中间件弹出一条消息,我们收到此消息的原因是 MVC 中间件看到了该 URL。这是对网站根目录的请求,该请求在 URL 中找不到控制器名称或操作名称。网站的根放弃处理该请求,并将请求传递给下一个中间件,即app.Run代码。路线模板