图 2.1 将 ASP.NET 和 Web 开发工作负载添加到 Visual Studio 安装
注意如果您是第一次阅读本书,安装英语语言包可能是一个不错的选择,以便 IDE 命令始终与示例和屏幕截图匹配。
2.3 创建网页接口项目
当我们在系统上安装了 .NET SDK 和 Visual Studio 2022 时,我们可以开始创建我们的第一个 Web API 项目。执行以下步骤:
- 启动 Visual Studio 2022。
- 选择“创建新项目”选项。
- 使用搜索框查找 ASP.NET 核心 Web API 项目模板,如图 2.2 所示。
图 2.3 配置 ASP.NET 核心 Web API 项目
警告如果要使用其他 .NET 版本,可以自由执行此操作。但请记住,本书中的某些源代码示例可能需要进行一些更改才能使用框架更新和/或重大更改。
单击“创建”按钮后,Visual Studio 将立即为新的 MyBGList 项目生成源代码,将其添加到具有相同名称的解决方案中,然后在 IDE 中打开它。一切就绪!
在继续之前,让我们快速检查一切是否正常。按 F5 键(或单击最上面的工具栏中的“运行”按钮)以在调试模式下启动项目。如果我们正确执行了所有操作,Visual Studio 应该自动启动我们的默认浏览器,指向 https:/ /localhost:<someRandomPort> 并显示图 2.4 中显示的页面。
图 2.5 Visual Studio 的“开始”按钮
应用名称的选项(在我们的方案中为 MyBGList)对应于 Kestrel。如我们所见,我们还可以选择要使用的Web浏览器,以及现在可以跳过的其他一些选项。
launchSettings.json 文件的 iisSettings 和配置文件部分包含 IIS Express 和 Kestrel 的配置设置。对于每个服务器,我们可以选择要使用的 HTTP 和 HTTPS 端口、启动 URL、启动应用程序之前要设置的环境变量等。
如图 2.5 所示,如果我们现在单击“开始”按钮(或选择“调试”>“开始调试”或按 F5),我们将看到 SwaggerUI 页面,该页面处理在两个浏览器的 launchUrl 选项中配置的 swagger 终结点。请注意,无论我们选择哪个 Web 服务器,都会显示图 2.4 中显示的 SwaggerUI 页面,因为浏览器已配置为使用该端点。唯一明显改变的是用于建立HTTPS连接的本地TCP端口,因为Visual Studio在创建项目时随机确定它们。让我们借此机会规范化这些端口。
注意我们将在后面的章节中广泛使用 SwaggerUI 页面及其内容,同时实现我们的示例 Web API。此外,第11章深入讨论了Swagger。
打开 launchSettings.json 文件,并更改其内容,如以下清单所示。更新的行和值以粗体显示。
清单 2.1 修改了 launchSettings.json 文件
{ "$schema": "https://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:40080", "sslPort": 40443 } }, "profiles": { "MyBGList": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "https://localhost:40443;http://localhost:40080", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } }}IIS Express 本地 URL 和 TCP 端口,用于 HTTP 和 HTTPS
Kestrel 本地 URL 和 TCP 端口,用于 HTTP 和 HTTPS
红隼起始页
红隼环境变量
IIS Express 起始页
IIS 快速环境变量
正如我们所看到的,我们已经为IIS Express和Kestrel设置了40080(HTTP)和40443(HTTPS)TCP端口。这个简单的调整确保了本书中引用的URL在我们的本地代码库中正常工作,无论我们要使用的Web服务器如何。
内置 launchSettings.json 文件中指定的其余设置暂时足够好,因此我们可以保留它们。但是,在关闭文件之前,让我们仔细看看“环境变量”部分,其中包含IIS Express和Kestrel的单个ASPNETCORE_ENVIRONMENT环境变量。
2.4.2 配置应用设置.json
让我们转到 appsettings.json 文件,该文件将应用程序配置设置存储在 JSON 键值对中。如果我们查看MyBGList Web API项目的自动生成代码,我们可以看到Visual Studio创建了该文件的两个实例:
- appsettings.json
- 应用设置。开发.json
在了解这些文件的工作原理之前,探索 ASP.NET Core 中的运行时环境的概念可能会很有用。
运行时环境
Web 应用程序开发通常至少涉及三个主要阶段:
- 开发,软件开发人员在其中执行调试会话
- 暂存,其中选定的一组用户(或测试人员)执行内部和/或外部测试
- 生产,其中应用可供最终用户使用
根据 .NET 约定,这些阶段称为环境,可以使用应用执行上下文中的DOTNET_ENVIRONMENT和/或ASPNETCORE_ENVIRONMENT环境变量进行设置。每当我们启动应用程序时,我们都可以通过相应地设置该环境变量来选择要面向的运行时环境。
提示如果我们还记得 launchSettings.json 文件的 “environmentVariables” 部分,我们已经知道如何在本地开发机器中设置 ASPNETCORE_ENVIRonMENT 变量。我们将在第 12 章部署 Web API 时学习如何在生产服务器中执行此操作。
应用设置文件
现在我们知道了所有这些,我们可以很容易地理解这两个appsettings文件的用途:
- appsettings.json 旨在存储将由所有运行时环境使用的配置设置,除非它们被特定环境特定的文件覆盖或补充。
- 应用设置。Development.json就是其中之一。放置在那里的设置将仅由开发环境使用(并被任何其他环境忽略),覆盖和/或集成 appsettings.json “通用”文件中存在的设置。
警告特定于环境的文件将在通用版本之后读取,从而覆盖其中存在的任何键值对。换句话说,如果我们使用开发环境运行我们的应用程序,则应用程序设置中存在每个键值对。Development.json 将被添加到 appsettings.json 文件中存在的键值对中,如果它们已经设置,则替换它们。
如果我们查看这两个 appsettings 文件,我们会看到一堆与日志相关的设置(在日志记录 JSON 键中),我们现在可以忽略这些设置。我们将有机会在第7章讨论日志记录技术时与他们一起玩。我们现在能做的是添加一个新的键/值对,以后可以帮助我们。打开 appsettings.json 文件,并将以下行(粗体)添加到现有 JSON 中:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "UseDeveloperExceptionPage": false}这个新的配置设置将为我们提供一些 appsettings 文件的练习,还允许我们在稍后将实施的实现技术之间切换。
2.4.3 玩程序.cs文件
让我们转到程序.cs文件,我们在第 1 章中简要介绍了该文件。我们已经知道,此文件在应用程序开始时执行,以注册和配置所需的服务和中间件来处理 HTTP 请求和响应管道。
事实上,由 ASP.NET Web API 模板创建的默认 Program.cs 文件与我们在第 1 章中看到的相同,因此我们不会在其中找到任何新内容。通过简要回顾一下,我们可以清楚地看到我们的 Web API 要使用的服务和中间件,如以下列表所示。
清单 2.2 Program.cs文件
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();控制器服务和中间件
招摇服务和中间件
HTTP 到 HTTPS 重定向中间件
ASP.NET 核心授权中间件
控制器服务和中间件
当我们在这里时,让我们借此机会添加一些有用的中间件,以帮助我们更好地处理错误和异常。
异常处理
在Program.cs文件中找到以下代码:
if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI();}将其替换为以下内容(以粗体标记的更改):
if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI(); app.UseDeveloperExceptionPage();}else{ app.UseExceptionHandler("/error");}正如我们所看到的,我们在 HTTP 管道中添加了新的中间件。仅当应用在开发环境中运行时,才会包含第一个添加项;第二个添加将仅存在于过渡和生产环境中。以下是此中间件的详细操作:
- DeveloperExceptionPageMiddleware - 顾名思义,此中间件从 HTTP 管道捕获同步和异步异常,并生成一个 HTML 错误页面(开发人员异常页面),其中包含有关异常的有用信息,例如堆栈跟踪、查询字符串参数、cookie 和标头。此信息可能会向潜在攻击者暴露配置设置或漏洞。出于这个原因,我们只在开发环境中使用它,以便这些有用但可能有害的信息仅供开发人员使用。
- 异常处理中间件 - 此中间件还处理 HTTP 级别的异常,但更适合非开发环境,因为它将所有相关的错误信息发送到可自定义的处理程序,而不是生成详细的错误响应并自动将其呈现给最终用户。
现在,尽管 DeveloperExceptionPageMiddleware 开箱即用,不需要任何额外的工作,但 ExceptionHandlingMiddleware 要求我们实现一个专用的处理程序。正如我们通过查看代码所看到的,我们已经传递了 /error string 参数,这意味着我们希望使用我们需要实现的专用 HTTP 路由来处理这些错误。
正如我们在第 1 章中已经知道的,我们有两种方法可以做到这一点:使用控制器或使用最小 API。让我们看看它们,然后选择最有效的一个。
使用控制器
让我们从基于控制器的方法开始。从 Visual Studio 的解决方案资源管理器中,执行以下步骤:
- 右键单击 MyBGList 项目的“控制器”文件夹,然后选择“添加>控制器”。将打开一个弹出窗口,要求我们选择要添加的控制器。
- 导航到左侧树视图中的“通用> API ”节点,选择“API 控制器 - 空”选项,然后单击“添加”按钮。
- 将新控制器命名为 ErrorController.cs,然后单击“确定”创建它。
我们将看到新的 ErrorController.cs 文件的内容:一个空类,我们可以用来添加我们的操作方法 — 具体来说,我们需要处理 /error/ 路由的操作方法,我们的 ExceptionHandlingMiddleware 将转发 HTTP 错误。下面是我们需要的操作方法的最小实现:
using Microsoft.AspNetCore.Mvc; namespace MyBGList.Controllers{ [ApiController] public class ErrorController : Controllerbase { [Route("/error")] [HttpGet] public IActionResult Error() { return Problem(); } }}要处理的 HTTP 路由
要处理的 HTTP 方法
返回给调用方的 HTTP 响应
我们返回的 Problem() 方法是 Controllerbase 类(我们的 ErrorController 扩展)的一种方法,它生成 ProblemDetail 响应 — 一种机器可读的标准化格式,用于基于 RFC 7807 (https://tools.ietf.org/html/rfc7807 指定 HTTP API 响应中的错误).简而言之,它是一个 JSON 文件,其中包含有关错误的一些有用信息:标题、详细信息、状态等。但是,由于我们在未指定任何参数的情况下调用 Problem() 方法,因此这些值将由 ASP.NET Core 使用从已引发的异常中获取的默认值自动设置。
使用最小 API
让我们看看如何使用最小 API 来实现相同的结果。在 Visual Studio 的解决方案资源管理器中,打开 Program.cs 文件,并在应用之前添加以下代码。MapControllers() 方法:
app.MapGet("/error", () => Results.Problem());就是这样。事实上,Minimal API 似乎是这场比赛的明显赢家,因为它允许我们使用单行代码获得与我们的 ErrorController 相同的结果,而无需创建专用文件。这个结果应该不足为奇:此场景是死简单路由操作的完美示例,其中最小 API 大放异彩,而控制器更适合复杂任务。
在接下来的章节中,我们将看到许多基于控制器的方法将报复的场景。目前,我们不妨删除 ErrorController.cs 文件,并将最小 API 单行代码保留在 Program.cs 文件中。不过,首先,让我们花几分钟时间讨论一下,如果我们保持 ErrorController.cs 在原地会发生什么。
路由冲突
控制器和最小 API 可以毫无问题地存在于同一个项目中,因此开发人员可以两全其美。但它们应配置为处理不同的路由。如果他们共享一个终端节点,会发生什么情况?
如果我们记得在第1章中学到的内容,我们已经知道了答案:程序.cs文件中首先出现的中间件首先处理HTTP请求,并可能终止它,从而防止另一个请求发挥作用。这种行为非常好,不会在HTTP生命周期中造成任何重大问题,除了浪费在我们项目的代码库中有一个无用的实现。
在我们当前的方案中,因为我们放置了最小 API 的应用。MapGet() 方法就在应用程序之前。MapControllers() 方法,“死代码”受害者将是我们的 ErrorController.cs 文件。如果一切正常,我们为什么要删除该控制器?我们不能把它留在那里吗?
回答该问题的最佳方法是再次按 F5 并执行我们的应用,然后再删除 ErrorController.cs 文件。图 2.6 显示了我们应该得到什么。
图 2.7 测试开发人员异常页面中间件
此结果是意料之中的,因为我们在开发环境中执行应用,由 launchSettings .json 文件中的 ASPNETCORE_ENVIRonMENT 变量指定。如果我们想测试 ExceptionHandlerMiddleware,我们需要做的就是将变量的值从开发更改为生产。
或者,我们可以充分利用我们添加到appsettings.json文件中的UseDeveloperExceptionPage键。实现此设置将允许我们在开发人员例外页面和 ExceptionHandler 之间切换,而无需更改应用程序的运行时环境。打开程序.cs文件,并替换代码
if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI(); app.UseDeveloperExceptionPage();}else{ app.UseExceptionHandler("/error");}使用此代码:
if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI();} if (app.Configuration.GetValue<bool>("UseDeveloperExceptionPage")) app.UseDeveloperExceptionPage(); else app.UseExceptionHandler("/error"); 从 appsettings.json 文件中检索该文本值
如果为 TRUE,则使用 DeveloperExceptionPageMiddleware
如果为 FALSE,则改用 ExceptionHandlerMiddleware
现在将使用 ExceptionHandlerMiddleware 而不是 DeveloperExceptionPageMiddleware,因为在 appsetting.json 文件中,UseDeveloperExceptionPage 键的值设置为 false。我们可以立即按 F5,导航到 https://localhost:40443/error/test URL,并接收 ProblemDetail JSON 响应:
{ "type":"https://tools.ietf.org/html/rfc7231#section-6.6.1", "title":"An error occurred while processing your request.", "status":500}注意此 JSON 输出在我们的方案中(目前)足够可行,因为它不会公开有关我们应用的潜在可利用信息。我们可以进一步自定义输出。我们可以使用方法重载支持的可选参数,将通用的“发生错误”标题替换为实际的 Exception 消息,为不同类型的错误提供不同的状态代码,等等。
现在我们已经完成这一系列测试,我们应该为开发环境重新启用 DeveloperExceptionPageMiddleware。我们可以打开appsettings .json文件并将UseDeveloperExceptionPage值从false更改为true,但这不是正确的做法。我们希望确保这样一个潜在的不安全页面只能被开发人员看到,记得吗?因此,重新启用它的正确方法是执行以下步骤:
- 打开应用设置。开发.json 文件。
- 添加一个 UseDeveloperExceptionPage 键(此文件中不存在该键)。
- 将键的值设置为 true。
以下是更新后的文件的外观(粗体换行):
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "UseDeveloperExceptionPage": true}现在我们放在应用程序设置中的值。每当我们的应用在开发运行时环境中启动时,Development.json 文件都会覆盖 appsettings.json 文件中的值,这正是我们想要的。
2.4.4 检查天气预报控制器
下一个要查看的文件是 WeatherForecastController.cs,我们可以在 /Controllers/ 文件夹中找到它。
注意按照 ASP.NET 约定,所有控制器类都必须驻留在项目的根级 /Controllers/ 文件夹中,并从 Microsoft.AspNetCore.Mvc.Controller 基类继承。
正如我们从第 1 章中知道的那样,控制器在 ASP.NET Core 中用于定义和分组处理 HTTP 请求(通过路由映射)并相应地返回 HTTP 响应的操作。如果我们看一下WeatherForecastController的源代码,我们可以看到它也不例外。此示例控制器旨在处理对 /WeatherForecast 路由的 HTTP GET 请求,并返回一个 HTTP 响应,其中包含一个包含五个 JSON 对象的数组,其中包含一些随机生成的日期、温度 C 和摘要属性值:
using Microsoft.AspNetCore.Mvc; namespace MyBGList.Controllers{ [ApiController] [Route("[controller]")] public class WeatherForecastController : Controllerbase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController (ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { return Enumerable.Range(1, 5) .Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } }}添加特定于 API 的行为
默认路由规则
ILogger 实例(通过依赖注入实例化)
处理 HTTP GET 到 /WeatherForecast 的操作
如果我们尝试执行此代码,我们会得到以下结果:
[{ date: "2021-12-03T02:04:31.5766653+01:00", temperatureC: 0, temperatureF: 32, summary: "Warm"},{ date: "2021-12-04T02:04:31.5770138+01:00", temperatureC: 23, temperatureF: 73, summary: "Freezing"},{ date: "2021-12-05T02:04:31.5770175+01:00", temperatureC: 40, temperatureF: 103, summary: "Freezing"},{ date: "2021-12-06T02:04:31.5770178+01:00", temperatureC: 47, temperatureF: 116, summary: "Cool"},{ date: "2021-12-07T02:04:31.577018+01:00", temperatureC: 36, temperatureF: 96, summary: "Mild"}]返回的对象是 C# WeatherForecast 类的 JSON 表示形式,该类在项目根文件夹的 WeatherForecast.cs 文件中定义。 正如我们通过查看其源代码所看到的,它是一个 POCO 类,其中包含一些可以轻松序列化为 JSON 输出的属性:
namespace MyBGList{ public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } }}注意 POCO 代表普通旧 CLR 对象,换句话说,一个没有依赖项、属性、基础结构问题、特殊类型或其他职责的普通类。
WeatherForecastController 和 WeatherForecast 示例类可用于了解 ASP.NET 控制器的工作原理,但它们不适合我们的具体方案。在处理与棋盘游戏相关的 API 时,我们不需要了解任何有关温度或预测的信息。出于这个原因,我们将删除这些文件或将它们从项目中排除,就像我们之前对 ErrorController.cs 文件所做的那样,并将它们替换为更相关的示例。
2.4.5 添加棋盘游戏控制器
让我们从POCO类开始,它将取代以前的天气预报。在 Visual Studio 的解决方案资源管理器中,执行以下步骤(清单 2.3):
- 删除现有的天气预报.cs文件。
- 右键单击 MyBGList 项目的根文件夹,从上下文菜单中选择“添加新项>”,然后创建一个新的 BoardGame.cs 类文件。
- 用托管一些棋盘游戏数据的 POCO 类填充新文件。
清单 2.3 BoardGame.cs文件
namespace MyBGList{ public class BoardGame { public int Id { get; set; } public string? Name { get; set; } public int? Year { get; set; } }}这个新类仍然是一个示例,但它与我们选择的方案更一致!让我们对控制器执行相同的操作。在 Visual Studio 的解决方案资源管理器中,执行以下步骤(清单 2.4):
- 导航到 /Controllers/ 文件夹,然后删除现有的 WeatherForecastController.cs 文件。
- 右键单击 /Controllers/ 文件夹,从上下文菜单中选择“添加>控制器”,创建新的 API 控制器 - 空,并将新文件命名为 BoardGamesController.cs。
- 删除 /api/ 前缀,因为我们不需要它。
- 添加一个新的操作方法,以使用我们创建的 BoardGame POCO 类返回棋盘游戏数据数组。
清单 2.4 BoardGame.cs文件
using Microsoft.AspNetCore.Mvc; namespace MyBGList.Controllers{ [Route("[controller]")] [ApiController] public class BoardGamesController : Controllerbase { private readonly ILogger<BoardGamesController> _logger; public BoardGamesController(ILogger<BoardGamesController> logger) { _logger = logger; } [HttpGet(Name = "GetBoardGames")] public IEnumerable<BoardGame> Get() { return new[] { new BoardGame() { Id = 1, Name = "Axis & Allies", Year = 1981 }, new BoardGame() { Id = 2, Name = "Citadels", Year = 2000 }, new BoardGame() { Id = 3, Name = "Terraforming Mars", Year = 2016 } }; } }}更新的路线模式
新的获取方法
就是这样。我们新的 BoardGamesController 将处理 /BoardGames 路由,并使用一个 JSON 数组进行响应,该数组包含过去 45 年左右发布的三款备受赞誉的棋盘游戏的一些相关示例信息。
我们的BoardGamesController的最小行为可以通过Minimal API通过几行代码轻松处理。下面是一个代码片段,我们可以将其放入 Program.cs 文件中,以从 Get() 操作方法获取相同的输出:
app.MapGet("/BoardGames", () => new[] { new BoardGame() { Id = 1, Name = "Axis & Allies", Year = 1981 }, new BoardGame() { Id = 2, Name = "Citadels", Year = 2000 }, new BoardGame() { Id = 3, Name = "Terraforming Mars", Year = 2016 }});此示例只是一个示例 JSON 响应,它模拟了更复杂的行为,其中通常包括重要的数据检索。在接下来的章节中,我们将使用实体框架核心从数据库管理系统 (DBMS) 获取棋盘游戏数据,甚至可能为用户更新它。当我们处理这些类型的操作时,基于控制器的方法变得方便,甚至可能比最小 API 更方便。出于这个原因,这次我们将保留控制器而不是更换它。
2.5 练习
建立对 ASP.NET 和Visual Studio的信心的最佳方法是,一旦我们了解了各种工具的工作原理,就立即练习使用它们。本节提供了一些有用的练习,使我们能够使用在本章中学到的技能进一步自定义我们的第一个 Web API 项目。每个练习都旨在修改单个文件,但通过完成所有练习,我们将能够实现一致的总体目标。
假设我们需要为一组选定的内部测试人员配置新的 MyBGList Web API,这些测试人员将能够通过一组给定的 TCP 端口访问我们的开发机器。以下是我们需要确保的细节的完整积压工作:
- 测试人员只能使用 55221 和 55222 TCP 端口。
- 测试人员只能使用 Kestrel Web 服务器。
- 用于测试应用的 Web 浏览器应从 BoardGamesController 的 Get() 操作方法返回的 BoardGames 的 JSON 列表开始。
- 必须允许测试人员(如开发人员)访问 SwaggerUI 页面,但不能访问开发人员例外页面,他们应该无法访问该页面。
- 测试人员需要为每个棋盘游戏检索两个附加字段:最小玩家和最大玩家。这些字段应包含棋盘游戏支持的最小和最大玩家数。
提示如果您觉得大胆,请停止阅读此处,并在没有进一步帮助的情况下开始练习(困难模式)。如果您对到目前为止所学的内容不太有信心,可以阅读以下部分,这些部分提供了所有相关步骤的一般指导,而不会泄露解决方案(宽松模式)。所有给定练习的解决方案都可以在 GitHub 的 /Chapter_02/Exercises/ 文件夹中找到。若要测试它们,请将 MyBGList 项目中的相关文件替换为该文件夹中的文件,然后运行应用。
2.5.1 luanchSettings.json
我们需要做的第一件事是确保测试人员能够通过给定的TCP端口访问本地机器。明智的做法是设置一个专用的运行时环境供他们使用。暂存环境似乎是完美的选择,因为它允许我们定义一些特定的配置设置,而无需更改生产和开发环境的配置,我们可能需要这些配置。我们可以通过更新launchSettings.json文件并通过以下方式为MyBGList项目配置Kestrel启动设置来执行这些任务:
- 将 TCP 端口 55221 用于 HTTP,将 55222 用于 HTTPS。
- 将运行时环境设置为“暂存”。
- 将起始终结点 URL 设置为由 BoardGamesController 的 Get() 操作方法处理的路由,以便 Web 浏览器在应用启动时自动显示该页面。
我们不需要更改 IIS Express 的设置,因为测试人员不会使用它。这些任务完成积压工作中的第 1、2 和 3 项。
2.5.2 appsettings.json
接下来要做的是为暂存运行时环境创建设置文件,并定义一些对所有环境都有效的默认行为,我们可以在需要时有条件地覆盖这些行为。以下是我们如何完成所有这些任务:
- 将新的 UseSwagger 配置设置添加到 MyBGList 应用设置,该设置对所有运行时环境都有效,值为 False。
- 将现有配置文件中相同的 UseSwagger 配置设置添加到开发环境中,值为 True。
- 为过渡环境创建新的配置文件,并覆盖设置,如下所示:
- 使用开发人员异常页面:假
- 使用招摇:真
这些任务还不会影响任何事情,但它们符合我们规范的第 4 项。
提示将暂存环境的 UseDeveloperExceptionPage 设置为 false 可能是多余的,因为该值已在通用 appsettings.json 文件中设置。但是,由于我们谈论的是包含潜在机密信息的页面,因此在给定环境中明确拒绝访问不会造成伤害。
2.5.3 Program.cs
现在我们有了正确的应用设置变量,我们可以根据应用的运行时环境,使用它们有条件地添加(或跳过)相关中间件。我们需要打开 Program.cs 文件并更改 SwaggerMiddleware 和 SwaggerUIMiddleware 的当前初始化策略,以确保仅在 UseSwagger 设置为 True 时使用它们。通过这样做,我们完成了积压的第 4 项。
2.5.4 BoardGame.cs
若要实现积压工作的第 5 项,我们需要向现有的 BoardGame POCO 类添加两个新属性。至于要使用的类型,最合适的选择是可为空的 int,因为我们用于 Year 属性;我们无法确定此类信息是否始终适用于所有棋盘游戏。
2.5.5 BoardGameController.cs
将这些属性添加到 BoardGame 类不足以在 JSON 文件中正确显示它们,除非我们希望它们始终为 null。因为我们目前正在处理示例数据,所以我们唯一能做的就是更新我们的 BoardGameController 的 Get() 方法并手动设置固定值。这项任务足以完成积压工作的第 5 项并完成练习。
我们剩下要做的就是选择 Kestrel 作为启动 Web 服务器,单击“开始”按钮(或按 F5)启动我们的 Web API 项目,看看会发生什么。如果我们正确执行了所有操作,我们的 Web 浏览器应该自动调用 https://localhost :55221/boardgames 端点并显示以下 JSON 响应:
[{ "id":1, "name":"Axis & Allies", "year":1981, "minPlayers":2, "maxPlayers":5},{ "id":2, "name":"Citadels", "year":2000, "minPlayers":2, "maxPlayers":8},{ "id":3, "name":"Terraforming Mars", "year":2016, "minPlayers":1, "maxPlayers":5}]如果我们取得了这个结果,我们就准备好继续前进了。
总结
- 若要创建 ASP.NET 核心应用,我们需要下载并安装 .NET Core SDK、.NET Core 运行时和 ASP.NET Core 运行时(除非您选择了自动执行这些操作的 IDE,例如 Visual Studio)。
- 我们还应该为自己提供一个合适的IDE,如Visual Studio:一个全面的Windows和macOS开发解决方案,我们将在本书中使用。Visual Studio 可以显著提高我们的工作效率,并帮助我们标准化开发过程,这要归功于任务运行程序、包管理器、集成源代码管理和语法突出显示等内置功能。
- Visual Studio 包含许多有用的模板,我们可以将其用作创建应用程序的样板,包括 ASP.NET Core Web API 模板,这是启动我们的 MyBGList Web API 项目的完美选择。
- Visual Studio 的 ASP.NET Core Web API 模板附带了一小组自动生成的文件:
- 用于设置服务和中间件的启动文件(程序.cs)
- 用于使用开发 Web 服务器启动应用的设置文件 (launchSettings.json)
- 一组配置文件,用于存储应用特定于环境的设置 (appsettings.json)
- 用于模拟数据对象的 POCO 类 (天气预报.cs)
- 一个控制器类,可以使用一些示例 JSON 数据(天气预报控制器.cs响应简单的 HTTP 请求)
- 在简要回顾模板文件和一些小的代码更改以了解它们的工作原理后,我们可以开始用一些与棋盘游戏相关的类替换内置的天气预报示例类。
- 在继续之前,通过一些练习来测试我们获得的知识可能会很有用,模拟来自客户的一系列请求(积压项)。
- 根据我们的信心,我们可以尝试在没有任何建议的情况下实现它们或遵循一些高级指导。
- 无论选择的复杂程度如何,进行此类练习都是测试我们当前技能并为即将到来的主题做准备的好方法。

