三、创建项目

在这一章中,我将向你展示如何创建一个包含 ASP.NET Core MVC 和 Angular 应用的项目,这意味着项目的两个部分都可以使用 Visual Studio 或 Visual Studio 代码来开发。这个项目构成了本书其余部分的基础,因为我将解释如何一起使用 Angular 和 ASP.NET Core MVC 来创建一个富 web 应用。表 3-1 给出了组合项目的背景。

表 3-1。

将组合项目放在上下文中

|

问题

|

回答

| | --- | --- | | 这是什么? | 一个合并的项目在一个文件夹结构中包含了 Angular 和 ASP.NET Core MVC。 | | 为什么有用? | 合并后的项目使得使用一个 IDE(如 Visual Studio)开发应用的两个部分变得容易,同时简化了使用 ASP.NET Core MVC web 服务向 Angular 提供数据的过程。 | | 如何使用? | 首先创建 Angular 应用,然后是 ASP.NET Core MVC。额外的 NuGet 包用于允许项目的两个部分在运行时一起工作。 | | 有什么陷阱或限制吗? | 一个合并的项目使管理开发过程变得更容易,但是你仍然需要 Angular 和 ASP.NET Core MVC 的良好工作知识来创建一个有效的应用。 | | 有其他选择吗? | 您可以分别开发应用的 Angular 和 ASP.NET Core MVC 部分,尽管这可能会使开发过程变得复杂。 |

小费

你可以从 https://github.com/Apress/esntl-angular-for-asp.net-core-mvc-3 下载本章的完整项目。这也是你可以找到这本书的更新和更正的地方。

准备创建项目

有几种不同的方法来创建一个结合 Angular 和 ASP.NET Core MVC 的项目。我在本书中使用的方法依赖于@angular/cli 包,它与。NET 工具来创建一个新的 MVC 项目。

使用点网新 Angular 命令

微软提供了一个模板,可以用来创建类似的项目结构(可以通过在命令行运行dotnet new angular来使用)。我在本章中使用的过程更加手动,但这意味着您将理解不同的构建模块如何组合在一起,因此当您没有得到预期的结果时,您会有一个更好的想法。

@angular/cli 包提供了一个命令行界面,简化了创建和使用新 angular 项目的过程。在开发过程中,Angular 代码被编译,包被自动交付给浏览器,很容易立即看到更改的效果。

组合开发的关键是通过 ASP.NET Core 运行时利用 Angular 开发工具,允许每个框架与其自己的工具链一起使用。要开始这个过程,打开一个新的 PowerShell 命令提示符并运行清单 3-1 中的命令来安装@angular/cli 包。

npm install --global @angular/cli@8.1.2

Listing 3-1.Installing the @angular/cli Package

这个命令需要一段时间来运行,因为这个包有许多必须下载和安装的依赖项。

小费

你必须严格按照图中所示的步骤进行,不能遗漏任何一步或改变顺序。如果你卡住了,那么你可以从源代码库中下载一个现成的项目,可以在 https://github.com/Apress/esntl-angular-for-asp.net-core-mvc-3 找到。

创建项目的 Angular 部分

第一步是创建一个新的 Angular 项目,使用清单 3-1 中安装的@angular/cli 包来完成。打开一个新的 PowerShell 提示符,导航到一个方便的位置,并运行清单 3-2 中所示的命令。输入命令时,将所有参数放在同一行。

ng new SportsStore --directory SportsStore/ClientApp --routing true --style css
--skip-tests true --skip-git true

Listing 3-2.Creating an Angular Project

@angular/cli 包提供了ng命令,ng new创建了一个新的 angular 项目。这个项目被命名为 SportsStore,--directory参数指定了项目文件的位置。在 ASP.NET Core MVC 项目中使用 web 应用框架时,通常会使用ClientApp文件夹的名称。

--routing--style参数将项目配置为使用 URL 路由进行导航,并使用常规 CSS 文件来设计 HTML 元素的样式。--skipTests--skipGit参数创建一个没有单元测试和 Git 源代码设置的项目,这两者在本书中都没有使用。

在安装过程中,您可能会看到消息,告诉您可选的依赖项已被跳过。这是正常的,可以忽略。当设置完成时,结果是一个名为SportsStore/ClientApp的文件夹,其中包含 Angular 项目的工具和配置文件,以及一些占位符代码,以帮助启动开发并检查开发工具是否正常工作。

启动 Angular 开发工具

使用命令提示符运行清单 3-3 中所示的命令,这些命令导航到项目文件夹并启动 Angular 开发工具。

cd SportsStore/ClientApp
npm start

Listing 3-3.Starting the Angular Development Tools

npm start命令启动 Angular 开发工具,这些工具负责生成交付给浏览器执行的 JavaScript 代码。项目准备就绪后,该命令将产生以下输出:

Hash: 38f7b5c53d9a2dfa3dbd
Time: 9000ms
chunk {main} main.js, main.js.map (main) 11.5 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 248 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.08 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 16.4 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.94 MB [initial] [rendered]
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
wdm: Compiled successfully.

第一次使用时,开发工具可能需要一些时间来启动和编译项目。一旦显示“编译成功”消息,打开一个新的浏览器窗口并导航到http://localhost:4200以查看添加到新 Angular 项目的占位符内容,如图 3-1 所示。

img/449717_2_En_3_Fig1_HTML.jpg

图 3-1。

运行 Angular 开发工具

编辑 Angular 项目

如果您使用的是 Visual Studio 代码,您可以通过在 PowerShell 提示符下在SportsStore文件夹中运行code .(单词代码,后跟一个句点)或者通过选择文件➤打开文件夹然后选择SportsStore文件夹来编辑项目。

如果您正在使用 Visual Studio,请在 Visual Studio 启动时选择“打开本地文件夹”选项(或者在 Visual Studio 已经运行时选择“文件”“➤”“打开➤文件夹”),然后选择SportsStore文件夹。

两个编辑器都会向你展示项目的内容,如图 3-2 所示,展示了 Visual Studio 代码和 Visual Studio 呈现的文件视图。

img/449717_2_En_3_Fig2_HTML.jpg

图 3-2。

编辑项目

3-2 描述了 SportsStore 项目中的关键文件,其中一些文件将在后面的章节中作为添加到示例应用中的功能使用。

表 3-2。

示例项目中的关键文件

|

名字

|

描述

| | --- | --- | | ClientApp | 这是 Angular 项目的根目录。 | | ClientApp/src | 这是应用的目录。 | | ClientApp/src/app | 这是包含 Angular 应用的逻辑和模板的目录,也是大多数 Angular 开发的焦点。 | | ClientApp/src/assets | 该目录包含要包含在应用中的静态内容,例如图像。 | | ClientApp/src/environments | 该目录包含不同开发环境的配置文件。项目是用开发和生产版本的配置创建的。 | | ClientApp/src/index.html | 该文件包含加载应用的 HTML。 | | ClientApp/src/main.ts | 这是 Angular 应用的入口点,这意味着该文件中的语句是应用启动时浏览器执行的语句。 | | ClientApp/src/polyfills.ts | 该文件配置应用使用的 polyfills,它提供对旧浏览器可能不支持的现代 JavaScript 功能的支持。 | | ClientApp/src/styles.css | 该文件定义了应用于整个应用的 CSS 样式。 | | ClientApp/angular.json | 该文件配置 Angular 构建工具。 | | ClientApp/package.json | 该文件跟踪 Angular 项目使用的包,并定义用于启动 Angular 开发工具和创建产品构建的命令。 | | ClientApp/tsconfig.json | 该文件包含 TypeScript 编译器的配置。 | | ClientApp/tsconfig.app.json | 该文件包含 TypeScript 编译器的附加配置设置,这些设置应用于app文件夹中的代码。 |

了解 Angular 工具链

Angular 开发中使用了三种重要的工具。第一个工具是 TypeScript 编译器,它负责将 TypeScript 代码编译成可由 web 浏览器执行的 JavaScript。

第二个工具是 webpack。TypeScript 编译器为它编译的每个 TypeScript 源文件生成一个 JavaScript 文件。这不是一种分发 web 应用的方便方法,因为每个文件都必须由浏览器请求,从而导致一系列对小代码文件的 HTTP 请求。相反,单独的 JavaScript 文件被组合成包,允许应用通过更少的 HTTP 请求被交付给浏览器。Angular 项目中的包是由 webpack 创建的,webpack 是 web 应用开发中最流行的包,与使用的框架无关(例如,React 和 Vue.js 开发中也使用 web pack)。命令的输出显示了 webpack 为示例项目创建的包;它们在表 3-3 中描述。这些是所有 Angular 应用将包含的包。

表 3-3。

示例应用包

|

名字

|

描述

| | --- | --- | | main.js | 这个包包含应用的代码和内容。 | | polyfills.js | 这个包包含在旧浏览器中支持现代 JavaScript 特性的代码。这个包的内容是使用ClientApp/src/polyfills.ts文件配置的。 | | runtime.js | 这个包包含加载和解包其他包文件所需的 JavaScript 代码。 | | styles.js | bundler 将应用的 CSS 样式表包含在这个包中,表示为 JavaScript 字符串。该包还包含 JavaScript 代码,用于处理编码字符串,并使用浏览器的 CSS API 将样式添加到 HTML 文档中。 | | vendor.js | 这个包包含 Angular 运行时,它负责处理main.js包的内容并将应用呈现给用户。 |

Angular 开发中的第三个重要工具是 Webpack 开发服务器(WDS ),它提供了一个 HTTP 服务器,将应用交付给浏览器。在开发过程中,交付给浏览器的包包含额外的 JavaScript 代码,这些代码打开一个到服务器的连接并等待信号。当检测到对项目文件的更改时,TypeScript 编译器用于编译代码,创建一组新的包,并将信号发送到浏览器以触发重新加载,从而确保更改的效果立即得到反映。图 3-3 显示了 Angular 工具链。

img/449717_2_En_3_Fig3_HTML.png

图 3-3。

Angular 开发工具链

要查看运行中的更新过程,用清单 3-4 中显示的内容替换ClientApp/src/app文件夹中的app.component.html文件的内容。

<h2>SportStore</h2>
<span>Angular Content Will Go Here</span>

Listing 3-4.Replacing the Contents of the app.component.html File in the ClientApp/src/app Folder

当对app.component.html文件的更改被更改时,Angular 工具链响应并产生以下输出:

Hash: 91ce339c6f84319ad47b - Time: 160ms
4 unchanged chunks
chunk {main} main.js, main.js.map (main) 10.4 kB [initial] [rendered]
wdm: Compiled successfully.

使用npm start命令时的初始准备可能需要几分钟,但后续的更改会更快,并且 Angular 工具仅重建其内容受更改文件影响的包。在这种情况下,main.js包被更新,重新加载信号被发送到浏览器,显示图 3-4 中的内容。

小费

在开发过程中,为了提高性能,包文件只保存在内存中,不写入磁盘。如第 13 章所示,只有当应用准备好进行部署时,才会创建磁盘文件。

img/449717_2_En_3_Fig4_HTML.jpg

图 3-4。

Angular 项目中已更改文件的效果

一旦您确认了实时更新功能正在运行,请使用 Control+C 停止 Angular 开发工具。

创建项目的 ASP.NET Core MVC 部分

一旦 Angular 项目建立起来,下一步就是创建一个 ASP.NET Core 项目。使用 PowerShell 命令提示符运行在SportsStore文件夹中的清单 3-5 中显示的命令。

mkdir ServerApp
cd ServerApp
dotnet new globaljson --sdk-version 3.0.100

Listing 3-5.Preparing for the ASP.NET Core MVC Project

这些命令创建了一个SportsStore/ServerApp文件夹,其中将包含 ASP.NET Core MVC 项目。dotnet new globaljson命令创建一个名为global.json的文件,指定。NET 核心运行时,这将有助于确保这些例子按预期工作。默认情况下,最新版本的。NET Core SDK 用于创建新项目,这可能意味着如果你安装的版本比第 2 章中指定的版本更高,你会得到不一致的结果。

运行SportsStore/ServerApp文件夹中清单 3-6 所示的命令来创建 ASP.NET Core MVC 项目。

dotnet new mvc --language C# --auth None

Listing 3-6.Creating the ASP.NET Core Project

dotnet new命令将一个基本的 ASP.NET Core MVC 项目所需的所有文件添加到SportsStore/ServerApp文件夹中,与本章前一节创建的 Angular 项目放在一起。Visual Studio 和 Visual Studio 代码都会检测到新文件,并显示在文件列表中,如图 3-5 所示。

img/449717_2_En_3_Fig5_HTML.jpg

图 3-5。

将 ASP.NET Core MVC 项目添加到 SportsStore 文件夹中

如果您正在使用 Visual Studio 代码,当您打开项目文件夹时,可能会提示您添加 C# 扩展,并且您可能会看到如图 3-6 所示的提示。

img/449717_2_En_3_Fig6_HTML.jpg

图 3-6。

提示安装 Visual Studio 代码的 C# 扩展

单击“是”按钮,Visual Studio 代码将下载并安装生成和调试 C# 代码所需的工具。Visual Studio 不需要添加任何内容。表 3-4 描述了示例 ASP.NET Core MVC 项目中的关键文件。

表 3-4。

示例项目中的关键文件

|

名字

|

描述

| | --- | --- | | Controllers | 该文件夹包含 MVC 控制器,负责接收请求和选择将被呈现以创建响应的视图。 | | Models | 该文件夹包含描述 ASP.NET Core MVC 应用使用的数据的模型类。 | | Properties/launchSettings.json | 该文件包含用于运行 ASP.NET Core MVC 应用的配置设置。 | | Views | 该文件夹包含用于生成 HTML 内容的 Razor 视图。 | | wwwroot | 该文件夹包含 ASP.NET Core MVC 应用使用的静态内容,如 CSS 样式表、图像和 JavaScript 包。 | | appsettings.json | 该文件包含应用的配置设置。 | | appsettings.Development.json | 该文件包含仅在开发过程中使用的附加配置设置。Visual Studio 解决方案资源管理器将该文件嵌套在appsettings.json文件中。 | | Program.cs | 这是 ASP.NET Core MVC 应用的入口点,应用启动时会调用这个入口点。 | | ServerApp.csproj | 这是项目文件,用于配置构建过程。该文件被 Visual Studio 隐藏。 | | Startup.cs | 该文件包含在运行时设置 ASP.NET Core 的语句,以及相关的特性,如 MVC 和实体框架核心。 |

为 Visual Studio 准备项目

如果您使用的是 Visual Studio 代码,ServerApp 项目将被自动检测并显示在文件窗格中。

如果使用的是 Visual Studio,选择文件➤打开➤项目/解决方案菜单,导航到SportsStore/ServerApp文件夹,选择SportsStore.csproj文件。Visual Studio 将在中打开该项目。NET 模式,并将隐藏以前在解决方案资源管理器窗口中显示的一些文件。

右键单击解决方案资源管理器窗口顶部的解决方案项,并从弹出菜单中选择添加➤现有网站。导航到SportsStore文件夹,选择ClientApp文件夹,然后单击打开按钮。Visual Studio 会将ClientApp文件夹添加到解决方案资源管理器中,这样你就可以看到 Angular 项目的内容,如图 3-7 所示。

img/449717_2_En_3_Fig7_HTML.jpg

图 3-7。

在 Visual Studio 中打开项目

右键单击 ClientApp 项,从弹出菜单中选择属性页,并导航到构建部分。确保“将网站作为解决方案的一部分”选项未被选中,如图 3-8 所示。

小费

如果该选项已经被取消选中,再次打开和关闭它,以确保它被禁用。Visual Studio 并不总是正确显示此设置。

此配置更改阻止 Visual Studio 尝试编译 Angular 项目中的代码。

img/449717_2_En_3_Fig8_HTML.jpg

图 3-8。

更改生成配置

选择文件➤全部保存;Visual Studio 将提示您保存解决方案文件,当您想开始一个开发会话时,该文件可用于打开 Angular 和 ASP.NET Core MVC 项目。使用名称SportsStore.sln将文件保存在SportsStore文件夹中。当需要再次打开项目时,打开SportsStore.sln文件;项目的两个部分都将打开并显示在解决方案资源管理器窗口中。

准备构建 ASP.NET Core MVC 应用

为了配置在使用 Visual Studio 启动应用时使用的端口,对ServerApp/Properties文件夹中的launchSettings.json文件进行清单 3-7 所示的更改。

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:5000",
      "sslPort": 5001
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "SportsStore": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Listing 3-7.Changing IIS Ports in the launchSettings.json File in the ServerApp/Properties Folder

无论应用是如何启动的,这些更改都可以确保一致性,以便在端口 5000 上接收 HTTP 请求,在端口 5001 上接收 HTTPS 请求。

再生发展 HTTPS 证书

最后的准备步骤是通过运行清单 3-8 中所示的命令来重新生成开发 HTTPS 证书。对于 Windows 显示的每个提示,选择“是”选项。

dotnet dev-certs https –clean

dotnet dev-certs https --trust

Listing 3-8.Regenerating the Windows Development Certificates

构建和运行 ASP.NET Core MVC 应用

项目的 ASP.NET Core MVC 部分可以从命令行或使用代码编辑器进行编译和执行。要从命令行构建并运行项目,运行清单 3-9 中的命令。

小费

如果您想构建项目而不执行它,请使用dotnet build命令。

dotnet watch run

Listing 3-9.Building and Running the ASP.NET Core MVC Project

ASP.NET Core MVC 项目将被编译,运行时将启动,产生以下输出:

...
watch: Started
info: Microsoft.Hosting.Lifetime[0] Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0] Content root path: C:\SportsStore
...

输出报告用于监听 HTTP 和 HTTPS 请求的端口,默认情况下,HTTP 端口为 5000,HTTPS 端口为 5001。打开浏览器窗口并导航至https://localhost:5001;您将看到如图 3-9 所示的占位符内容。

注意

您可能会看到一个安全警告,这是由于用于开发的证书是自签名的而触发的。大多数浏览器会提供一个“高级”选项,允许你继续。如果您收到一个 ERR _ SPDY _ improval _ TRANSPORT _ SECURITY 错误,那么可能的原因是您跳过了清单 3-8 中的dotnet dev-certs命令。

img/449717_2_En_3_Fig9_HTML.jpg

图 3-9。

运行 ASP.NET Core MVC 应用

了解 ASP.NET Core MVC 工具链

ASP.NET Core MVC 的开发工具与 Angular 使用的完全不同。C# 编译器处理 C# 代码文件中的语句,并生成可由。NET 核心运行时。当应用启动时,HTTP 请求由互联网信息服务(IIS)或独立的 ASP.NET Core Kestrel 服务器接收,并由 ASP.NET Core 请求管道处理,该管道是 ASP.NET Core 应用的主干,允许 MVC 应用、RESTful web 服务和其他框架在同一应用中共存。

用于创建项目的模板包括 MVC 框架。请求由定义在ServerApp/Controllers文件夹中的Home控制器处理,它选择ServerApp/Views/Home文件夹中的Index.cshtml视图文件。MVC 框架使用 Razor 视图引擎来处理视图,生成发送回浏览器并显示给用户的 HTML。图 3-10 为工具链。

img/449717_2_En_3_Fig10_HTML.png

图 3-10。

ASP.NET Core MVC 工具链

请求管道是 ASP.NET Core 的心脏,它是围绕一系列中间件组件构建的,这些中间件组件能够检查请求并修改它们或产生结果。这本书最有趣的中间件集成了 MVC 框架,但几乎每个 ASP.NET Core 功能都在某种程度上依赖于中间件,包括提供静态内容和将 HTTP 请求重定向到 HTTPS URL。

用于启动应用的dotnet watch run命令。NET Core 进入监视模式,这样它可以检测到对ServerApp文件夹中文件的更改,并自动重新编译代码和重启应用。要查看更新过程,在ServerApp/Views/Home文件夹中添加一个名为Placeholder.cshtml的文件,内容如清单 3-10 所示。

注意

dotnet watch run命令很有用,但是它有局限性,最严重的是它不能检测新文件。在这本书里,我会告诉你什么时候必须使用 Control+C 停止 ASP.NET Core 运行时,然后再启动。

如果您使用的是 Visual Studio,请在解决方案资源管理器中右击 ServerApp/Views/Home 项,并从弹出菜单中选择“添加➤视图”。将视图名称设置为占位符,选择“空(无模型)”模板,忽略其他设置,然后单击“添加”按钮。(添加视图时,您可能需要停止 ASP.NET Core 运行时,因为 Visual Studio 可以尝试构建项目,这需要访问由 ASP.NET Core 锁定的文件。)

如果您使用的是 Visual Studio 代码,右键单击ServerApp/Views/Home文件夹,从弹出菜单中选择 New File,并使用Placeholder.cshtml作为文件名。

@{
    ViewData["Title"] = "Placeholder";
}

<h2>SportStore</h2>
<span>ASP.NET Core MVC Content Will Go Here</span>

Listing 3-10.The Contents of the Placeholder.cshtml File in the ServerApp/Views/Home Folder

要应用新的视图,更改ServerApp/Controllers文件夹中HomeController.cs文件的内容,如清单 3-11 所示。

using Microsoft.AspNetCore.Mvc;
using ServerApp.Models;
using System.Diagnostics;

namespace ServerApp.Controllers {

    public class HomeController : Controller {

        public IActionResult Index() {
            return View("Placeholder");
        }

        public IActionResult Privacy() {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None,
            NoStore = true)]
        public IActionResult Error() {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id
                ?? HttpContext.TraceIdentifier });
        }
    }
}

Listing 3-11.Using a New View in the HomeController.cs File in the ServerApp/Controllers Folder

文件更改将被dotnet watch命令检测到,这将停止 ASP.NET Core 运行时,构建项目,并再次启动运行时。与 Angular 不同,需要手动重新加载才能在浏览器中看到更改的效果,如图 3-11 所示。

img/449717_2_En_3_Fig11_HTML.jpg

图 3-11。

改变 ASP.NET Core MVC 应用呈现的内容

连接 Angular 和 ASP.NET Core 应用

Angular 和 ASP.NET Core MVC 应用共享相同的父文件夹,但没有以任何方式连接。用这种方式开发应用是可能的,但是很笨拙。一个更有用的方法是连接这两个工具链,以便 HTTP 请求被 ASP.NET Core 接收,并被传递给 MVC 框架或基于请求 URL 的 Angular 开发工具。

连接工具链有两种方法,每种方法在项目生命周期的不同阶段都很有用。在接下来的小节中,我将演示这两种方法,并解释每种方法何时有用以及如何在它们之间切换。这两种方法都依赖于额外的。网包。打开一个新的 PowerShell 命令提示符,导航到SportsStore/ServerApp文件夹,运行清单 3-12 中所示的命令。

dotnet add package Microsoft.AspNetCore.SpaServices.Extensions --version 3.0.0

Listing 3-12.Adding a Package to the ASP.NET Core Project

微软提供的Microsoft.AspNetCore.SpaServices.Extensions包允许单页应用(SPA)框架,如 Angular,与 ASP.NET Core 一起使用。

通过 ASP.NET Core 管理 Angular 服务器

最常用的连接技术是配置 ASP.NET Core 运行时,以便它在收到第一个 HTTP 请求时启动 Angular development server。这样做的好处是只需要一个命令就可以启动两个工具链,这可以通过命令行或使用 Visual Studio 和 Visual Studio 代码提供的内置功能来完成。缺点是重启 ASP.NET Core 也将重启 Angular development server,这意味着每次重启都会重复初始编译过程,每次可能需要 10 到 20 秒。

将清单 3-13 中所示的代码添加到Startup类中,以配置 ASP.NET Core,使其负责管理 Angular development 服务器并根据配置设置选择连接方式。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

using Microsoft.AspNetCore.SpaServices.AngularCli;

namespace ServerApp {
    public class Startup {

        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services) {
            services.AddControllersWithViews();
            services.AddRazorPages();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
            } else {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();

            app.UseEndpoints(endpoints => {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
            });

            app.UseSpa(spa => {
                spa.Options.SourcePath = "../ClientApp";
                spa.UseAngularCliServer("start");
            });
        }
    }
}

Listing 3-13.Configuring the Application in the Startup.cs File in the ServerApp Folder

新代码调用UseSpa方法向 ASP.NET Core 请求管道添加一个中间件组件。UseSpa方法的参数是一个接收配置对象的函数;在此示例中,参数用于指定 Angular 项目的位置,并指定用于启动 Angular 开发工具的 NPM 命令。UseSpa方法仅在开发中使用,在第 13 章部署应用之前将被移除。

ASP.NET Core 按照中间件组件被定义的顺序来处理它们,这意味着 Angular development server 将只接收那些没有被其他中间件组件处理的请求,比如那些应用 MVC 框架的组件。

使用 Control+C 来停止 Angular development server 和 ASP.NET Core 运行时,然后使用命令提示符来运行在ServerApp文件夹中的清单 3-14 中显示的命令。

小费

您也可以选择“调试➤启动,不调试 Visual Studio 和 Visual Studio 代码”。但是,根据您选择的 IDE,您可能会发现对 C# 类的更改不会触发自动重新编译和重新启动。

dotnet watch run

Listing 3-14.Starting the Development Servers

打开网络浏览器并导航至https://localhost:5001;你会看到 MVC 框架生成的内容,如图 3-12 第一张截图所示。

接下来,导航到https://localhost:5001/app;您将看到 Angular 应用的输出,如图 3-12 中的第二个截图所示。

第一个 URL 由 MVC 框架处理,因为默认的 URL 被Startup类中的这个语句翻译成对Home控制器上的Index动作的请求:

...
app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
});
...

第二个 URL 的app段不对应一个 MVC 控制器的名字,所以 MVC 框架不能处理这个请求,然后这个请求被转发到 Angular development server。/app URL 没有特殊的意义,任何包含与控制器名称不匹配的段的 URL 都会有同样的效果。(忽略当显示 Angular 应用时,您可能会在浏览器的 JavaScript 控制台中看到的错误。)

img/449717_2_En_3_Fig12_HTML.jpg

图 3-12。

将请求转发到 Angular development 服务器

在后台,ASP.NET Core 中间件启动 Angular development server,并转发其他中间件组件(如 MVC 框架)不处理的 HTTP 请求,如图 3-13 所示。

img/449717_2_En_3_Fig13_HTML.png

图 3-13。

使用单独的服务器进行开发

每次 ASP.NET Core 运行时重启时,Angular development server 也将重启,直到初始编译阶段完成后才能响应请求。

一旦您请求了这两个 URL,使用 Control+C 来停止 ASP.NET Core 运行时。Angular development 服务器也将被终止。

使用 ASP.NET Core MVC 代理特性

另一种连接技术是从 ASP.NET Core 运行时单独启动 Angular 开发工具。请求仍然被转发到 Angular 服务器,但是 ASP.NET Core 运行时不负责启动 Angular 工具。在这种方法中,重启更快,这可以在迭代开发期间创建更平滑的流程。项目的每个部分都独立响应,因此,例如,对 C# 类的更改不会影响 Angular development server。这种方法的缺点是,您需要运行两个命令并监视两个输出流来查看消息和错误。

将清单 3-15 中所示的语句添加到Startup类中,以配置 ASP.NET Core MVC 将请求转发到 Angular development server,以及根据配置设置选择连接技术的语句。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.SpaServices.AngularCli;

namespace ServerApp {
    public class Startup {

        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services) {
            services.AddControllersWithViews();
            services.AddRazorPages();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
            } else {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();

            app.UseEndpoints(endpoints => {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
            });

            app.UseSpa(spa => {
                string strategy = Configuration
                    .GetValue<string>("DevTools:ConnectionStrategy");
                if (strategy == "proxy") {
                    spa.UseProxyToSpaDevelopmentServer("http://127.0.0.1:4200");
                } else if (strategy == "managed") {
                    spa.Options.SourcePath = "../ClientApp";
                    spa.UseAngularCliServer("start");
                }
            });
        }
    }
}

Listing 3-15.Configuring the Application in the Startup.cs File in the ServerApp Folder

Configuration对象用于读取DevTools部分中ConnectionStrategy的值。如果设置为managed,则使用上一节的技术。如果设置是proxy,那么UseSpa方法用于指定 Angular 服务器的 URL 作为UseProxyToSpaDevelopmentServer方法的参数。

要选择管理选项,将清单 3-16 中所示的配置设置添加到appsettings.Development.json文件中。(如果您使用的是 Visual Studio,可以通过在解决方案资源管理器窗口中展开appsettings.json文件项来访问该文件。)

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "DevTools": {
      "ConnectionStrategy": "proxy"
  }
}

Listing 3-16.Adding Configuration Settings in the appsettings.Development.json File in the ServerApp Folder

要启动 Angular development server,打开一个新的 PowerShell 命令提示符,导航到SportsStore/ClientApp文件夹,并运行清单 3-17 中所示的命令。

npm start

Listing 3-17.Starting the Angular Development Server

要启动 ASP.NET Core 服务器,打开第二个 PowerShell 提示符,导航到SportsStore/ServerApp文件夹,运行清单 3-18 中所示的命令。

dotnet watch run

Listing 3-18.Starting the ASP.NET Core Server

一旦两个服务器都在运行,打开一个新的浏览器,导航到https://localhost:5001,然后是https://localhost:5001/app。您将看到与上一节相同的结果,因为请求是以相同的方式转发的。不同的是,Angular 服务器是独立启动的。

更新控制器、视图和布局

当 ASP.NET Core 无法处理请求时,它会被转发到 Angular development 服务器。如果请求 URL 没有指定其中一个包文件或来自assets文件夹的文件,Angular development server 会返回ClientApp/src文件夹中的index.html文件,静态内容通常存储在独立的 Angular 项目中。

为了增加 Angular 和 MVC 框架之间的集成,我将更新默认的 Razor 布局和Views/Home/Index视图,以便 Angular 服务器只交付包文件。首先,用清单 3-19 中所示的元素替换ServerApp/Views/Shared文件夹中_Layout.cshtml文件的内容。

<!DOCTYPE html>
<html lang="en">
<head>
    <base href="/">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SportsStore</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
    <h2 class="bg-dark text-white p-2">SportStore</h2>
    @RenderBody()
    @RenderSection("Scripts", required: false)
</body>
</html>

Listing 3-19.Replacing the Contents of the _Layout.cshtml File in the ServerApp/Views/Shared Folder

该布局包括 Bootstrap CSS 样式表,我将在本书中使用它来设计 HTML 元素的样式(Bootstrap 是通过用于创建项目的dotnet new命令添加到项目中的)。主体部分和script元件将包含 Angular 应用包。为了提供应用所需的内容和script元素,将ServerApp/Views/Home文件夹中的Index.cshtml文件的内容替换为清单 3-20 中所示的元素。

@section scripts {
    <script src="runtime.js"></script>
    <script src="polyfills.js"></script>
    <script src="styles.js"></script>
    <script src="vendor.js"></script>
    <script src="main.js"></script>
}

<app-root></app-root>

Listing 3-20.Replacing the Contents of the Index.cshtml File in the ServerApp/Views/Home Folder

scripts部分包括表 3-3 中描述的每个包文件的script元素。app-root元素是应用运行时 Angular 应用的内容将被插入的目标。为了确保使用新视图,更改Home控制器上的Index动作,如清单 3-21 所示。

using Microsoft.AspNetCore.Mvc;
using ServerApp.Models;
using System.Diagnostics;

namespace ServerApp.Controllers {

    public class HomeController : Controller {

        public IActionResult Index() {
            return View();
        }

        public IActionResult Privacy() {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None,
            NoStore = true)]
        public IActionResult Error() {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id
                ?? HttpContext.TraceIdentifier });
        }
    }
}

Listing 3-21.Using a Different View in the HomeController.cs File in the ServerApp/Controllers Folder

保存更改,允许 ASP.NET Core 运行时重新启动,并使用浏览器导航到https://localhost:5001。你会看到 Razor 视图已经包含了显示 Angular 应用所需的元素和包文件,如图 3-14 所示。

img/449717_2_En_3_Fig14_HTML.jpg

图 3-14。

使用 Razor 视图显示应用

摘要

在这一章中,我向你展示了如何创建一个结合 Angular 和 ASP.NET Core MVC 的项目。这个过程有点复杂,但结果是一个坚实的基础,允许应用的 Angular 和 MVC 部分一起工作,同时保留它们各自使用的工具链。在下一章中,我将开始数据模型的工作,它将支撑 ASP.NET Core MVC 和项目的 Angular 部分。