ASP.NET Core 基础知识(一)

原文:ASP.NET Core Essentials

协议:CC BY-NC-SA 4.0

零、前言

Web 应用在企业应用开发中蓬勃发展,即使移动应用继续流行。 此外,web api 的使用提供了更大的灵活性,当涉及到构建一个后端,可以同时服务于 web 应用和移动应用。 ASP.NET Core 1.0,你可以从成熟的编程语言(如 c#)中获得好处,它具有全新的。NET Core 的性能,允许你的 web 应用和 web api 在 Windows、Mac 和 Linux 上运行。

ASP.NET Core 允许您在开发期间选择操作系统,无论您是在 Surface Book、MacBook Air 还是在流行的 Linux 发行版上编写代码。 虽然本书主要涵盖了在 Windows 系统上使用 Visual Studio 2015 进行开发,但如果你希望在不同的操作系统上设置环境,你可以找到在线指南的链接。

ASP.NET Core 1.0 Essentials 将向你介绍微软的最新版本.NET,以及你今天开始所需要的一切。 如果你已经用过 ASP.NET MVC 之前,您将得到一些您已经知道的东西,然后是新的东西。 如果你只使用 ASP.NET Web Forms 或其他竞争的 Web 框架,你会发现最初的章节非常有用,为你需要知道的东西奠定了基础。

这本书的内容

第一章ASP 入门 asp.net Core,教你如何使用 ASP.NET Core 1.0,包括 MVC 和 web API。 本章将解释完整的。net Framework 4.6 和。net Core 之间的区别,同时介绍 Visual Studio 2015 和全新的跨平台 Visual Studio Code。

第二章asp.NET Core 应用,展示了如何创建一个新的 asp.NET Core 应用.NET Core web 应用。 本章将剖析现代 ASP 的各个部分.NET web 应用,同时解释什么是新的和什么改变了。

第三章,了解 MVC,将会让您了解 ASP.NET Core MVC 通过深入到控制器、视图和模型。 本章将解释如何创建一个现代 MVC 应用的所有部分,然后将它们结合在一起。

第四章,Using Web API to Extend Your Application,是关于使用 Web API 来扩展你的 Web 应用来支持 Web 和移动应用。 本章将解释如何创建路由和配置 web API 应用,然后从客户端应用使用它。

第五章,使用 JavaScript 与 Web API 交互,教你如何与 ASP 交互.NET web API 使用直接的 JavaScript 以及流行的框架,如 AngularJS 和 KnockoutJS。 本章还将介绍开发人员工具,这些工具可以在开发过程中自动化重要的任务和帮助。

第 6 章,使用实体框架在代码中与数据库交互,教你如何在 web 应用的数据层中使用实体框架。 本章将介绍对象关系映射(ORM)工具和 EF 代码优先迁移的使用。

第七章,依赖注入和健壮 Web 应用的单元测试,展示了如何使用控制反转实现依赖注入。 本章将介绍 DI、IoC 容器,以及微软对依赖注入的新内置支持。 本章还将涵盖单元测试的基础知识。

第 8 章认证、授权和安全是关于在 ASP 中启用认证的.NET web 应用,同时实现特定应用特性的授权。 本章还将涵盖保护用户数据的指导方针,以及对抗 web 应用中常见安全漏洞的策略。

第九章,部署你的应用,讲述了如何将你的应用部署到 web 服务器上的 IIS 或者微软的 Azure 云平台上。 本章还将介绍如何使用持续集成来运行单元测试和部署成功编译的应用。

你需要什么来写这本书

学习 ASP.NET Core 和运行代码示例为本书,推荐使用以下软件:

  • Windows 7 或更高版本(推荐 Windows 10)
  • Visual Studio 2015 Update 3 或更高版本(免费社区版可以)
  • 任何现代网络浏览器,如 Microsoft Edge,谷歌 Chrome,或 Mozilla Firefox
  • 可选:Visual Studio Code (Windows, Mac, Linux)

有关开发和运行 ASP 的更多信息。 在 Windows 以外的系统上运行 asp.net Core,请参考运行 ASP.NET Core on Windows, Mac OS X, Linuxsection inChapter 1NET Core。 在那里,你会看到 Mac 和 Linux 操作说明的高级概述,还有经常更新的在线指南链接。

这本书是写给谁的

这本书是为那些有。net 经验的软件开发人员编写的,最好使用 c#或其他一些面向对象的编程语言,这些语言是构建 ASP 所必需的.NET Core web 应用。 对 web 应用开发的基本理解也是必不可少的。

约定

在这本书中,你会发现许多不同的文本样式来区分不同种类的信息。 下面是这些风格的一些例子以及对它们含义的解释。

文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 url、用户输入和 Twitter 句柄如下所示:“使用 HTTPGET方法和可选的querystring参数”

一段代码设置如下:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

任何命令行输入或输出都写如下:

dotnet restore
dotnet build
dotnet ef migrations add Initial
dotnet ef database update

新词语、重要词语以粗体显示。 您在屏幕上看到的字,例如菜单或对话框中,会出现如下文本:“输入一些值并单击Create按钮。”

注意事项

警告或重要说明显示在这样的框中。

提示

提示和技巧是这样的。

读者反馈

我们欢迎读者的反馈。 让我们知道你对这本书的看法——你喜欢或不喜欢这本书。 读者反馈对我们来说很重要,因为它能帮助我们开发出你能真正从中获益最多的游戏。 要给我们发送一般性的反馈,只需发送电子邮件 feedback@packtpub.com,并在邮件主题中提到这本书的标题。 如果有一个主题,你有专业知识,你有兴趣写或贡献一本书,请参阅我们的作者指南www.packtpub.com/authors

客户支持

现在,你已经自豪地拥有了一本书,我们有一些东西可以帮助你从购买中获得最大的好处。

示例代码下载

您可以从您的帐户http://www.packtpub.com下载本书的示例代码文件。 如果您在其他地方购买这本书,您可以访问http://www.packtpub.com/support并注册,将文件直接通过电子邮件发送给您。

你可以按以下步骤下载代码文件:

  1. 使用您的电子邮件地址和密码登录或注册我们的网站。
  2. 将鼠标指针悬停在顶部的SUPPORT标签上。
  3. 点击代码下载&勘误表
  4. Search框中输入书名。
  5. 选择您想要下载代码文件的书。
  6. 从下拉菜单中选择你购买这本书的地方。
  7. 点击代码下载

下载文件后,请确保使用最新版本的解压或解压缩文件夹:

  • WinRAR / 7-Zip for Windows
  • Mac 的 Zipeg / iZip / unarx
  • 7-Zip / PeaZip for Linux

该书的代码包也托管在 GitHub 上的https://github.com/PacktPublishing/ASPdotNET-Core-Essentials。 我们在https://github.com/PacktPublishing/中还提供了丰富的图书和视频目录中的其他代码包。 检查出来!

勘误表

尽管我们已经竭尽全力确保内容的准确性,但错误还是会发生。 如果你在我们的书中发现错误,也许是文本或代码上的错误,如果你能向我们报告,我们将不胜感激。 通过这样做,您可以使其他读者免受挫折,并帮助我们改进这本书的后续版本。 如果您发现任何勘误表,请访问http://www.packtpub.com/submit-errata,选择您的图书,点击勘误表提交表格链接,并输入您的勘误表详细信息。 一旦您的勘误表被核实,您的提交将被接受,勘误表将被上载到我们的网站或添加到该标题的勘误表部分下的任何现有勘误表列表中。

要查看之前提交的勘误表,请访问https://www.packtpub.com/books/content/support并在搜索字段中输入书名。 所需资料将出现在勘误表部分。

盗版

在互联网上盗版受版权保护的材料是一个贯穿所有媒体的持续问题。 在 Packt,我们非常重视版权和授权的保护。 如果您在互联网上发现我们的作品以任何形式的非法拷贝,请立即提供我们的地址或网站名称,以便我们进行补救。

请通过 copyright@packtpub.com 与我们联系,并提供疑似盗版材料的链接。

我们感谢您的帮助,保护我们的作者和我们的能力,为您带来有价值的内容。

问题

如果您对本书的任何方面有任何问题,您可以通过 questions@packtpub.com 与我们联系,我们将尽最大努力解决问题。

一、开始使用 ASP.NET Core

活动服务器页面于 20 世纪 90 年代中期首次在微软的 IIS web 服务器上提供。 快进 20 年左右,ASP。 asp.net Core(即 asp.net; 现在,Visual Studio是开放源代码的,可以在 Windows、Linux 和 OS x 上运行。此外,除了 Windows 上的全功能 IDE 外,Visual Studio现在是一个跨平台的轻量级代码编辑器。

作为一个**. net的开发人员,您可以利用所有最近的改进,同时构建您已有的经验。 . net Framework 已经超越了完整的框架,现在可以作为一个名为. net Core**的跨平台运行时使用。

在本章中,我们将讨论以下原则和概念,让你开始使用 ASP.NET Core:

  • net 架构
  • ASP.NET 统一编程模型
  • 新的 Visual Studio ide
  • 跨平台运行时

NET Core -统一 MVC、Web API 和 Web 页面

当开发人员听到术语ASP。 asp.net,一些人将它与 asp.net 联系起来。 asp.netWeb Forms,而其他人认为asp.netWeb Forms**.NET MVC甚至Web API**。 许多开发人员已经开始了他们的 Web 表单之旅,并且在最近几年已经迁移到模型-视图-控制器(MVC)。

ASP 的采用。 由于其干净的代码和可测试性,NET MVC 多年来一直在崛起。 而你仍然可以在。net 4 上开发 Web Forms。 x,你将在。net Core 1.0 上使用 MVC。 幸运的是,ASP.NET Core 运行在。NET 4.5.1+和。NET Core 上,所以你可以选择你想要的运行时。

展望未来,微软在 ASP 中统一了 MVC、Web API 和 Web 页面。 净的核心。 这对作为开发者的你来说意味着什么? 这意味着在使用 MVC、Web API 和 Web 页面构建应用时,您将享受到更大的一致性。 在过去,MVC 和 Web API 是分开实现的,这导致了重复和不一致,但使用 ASP.NET Core,它们被合并成一个单一的编程模型。

高层概述

如果你对上述任何一个术语都不熟悉,这里有一个高层次的概述:

  • **NET MVC:**微软 MVC 架构模式的实现,用于构建健壮且轻量级的测试友好的 web 应用。
  • **Web API:**微软对 RESTful API 的回应,Web API 允许开发者构建 HTTP 服务,作为 Web 应用和移动应用的后端。
  • **网页:**微软创建轻量级动态网站的解决方案。 在撰写本文时,Web 页面在 asp.net Core 1.0 中是不可用的,所以在本书中不会涉及到它。

下图说明了一个典型的 ASP.NET web 应用,使用 MVC 和 web API。 请注意,Web API 可以用于 Web 浏览器以外的客户端,比如移动应用。 值得一提的是,这里的浏览器也可以包括移动网页浏览器:

<graphics/4921_01_01-1.jpg>

版本号

您可能已经注意到,我在谈论 ASP 时提到了 MVC 6。 净的核心。 ASP.NET MVC 6 已经被重命名为 ASP .NET Core 1.0 MVC。 为了记录所有的新版本号码,以下列出了你需要知道的信息:

  • c# 6.0
  • ASP.NET Core:
    • 运行在。net Core 1.0 或。net Framework 4.5.1+上
  • .NET Framework 4.6.2(撰写本文时)
  • net 1.0 核心
  • ASP.NET Core 1.0 MVC
  • SignalR 3(在撰写本文时尚未发布)

<graphics/4921_01_02-1.jpg>

把它们放在一起

现在您已经熟悉了 ASP 的移动部分.NET Core 和它的各种版本号,你将如何决定使用哪些部分? 好消息是,在你开始你的项目之前,你不需要弄清楚所有的事情。

考虑一下您的 web 软件项目的需求和客户的需求。 选择对你和你的团队有意义的技术,开始着手于最小可行产品(MVP)。

如果你需要支持网页浏览器,使用 ASP.NET MVC,并构建响应性良好的 web 应用,在任何屏幕尺寸上看起来都很好。 如果需要使用 Web API 扩展应用,那么只公开需要公开的内容。

如果您需要实时功能,SignalR是一个很好的起点。 在撰写本文时,微软已经宣布 SignalR 3 将不会包含在 ASP 1.0 发行版中。 净的核心。 因此,本书将不涉及 signalr3。 更多信息请关注 SignalR 网站:http://www.asp.net/signalr

.NET Framework 和.NET Core 的区别

自从。net 框架出现以来,每次都只发布一个版本。 每当有新版本发布时,您都可以升级到最新版本或同时安装多个版本。 但总是有一个最新的版本。

展望未来,现在有两个截然不同的版本:完整的。net 框架和全新的。net Core。 而 ASP.NET Core web 应用可以在其中任何一个平台上运行,您将决定哪一个更适合您的需要。 您可以在开发期间或发布期间更改运行时。 最好的是,您可以将运行时与发布的产品一起部署,这样就可以将. net 的多个版本部署到同一台服务器上。

下面的截图说明了 ASP.NET Core 运行在。NET Framework 4.6 和。NET Core 1.0 上:

<graphics/4921_01_03-1.jpg>

完整的。net Framework 4.6

即使有了。net Core 的发布,完整的。net 框架仍然有一席之地。 它将继续是富 Windows 桌面应用的首选框架,这些应用是用Windows Presentation Foundation(WPF)或 Windows 窗体创建的。 它将是两个选择之一的 ASP.NET Core 开发人员。

ASP.NET 4 的开发者们,.NET Framework 4.6 将会成为。NET 4 的替代。 x 运行时。 这包括。net 4、4.5、4.5.1 和 4.5.2。 升级到。net 4.6 的一个很好的理由是新的改进带来的好处,比如更好的编译和添加的语言特性。

轻量级。net Core

新的。net Core 是完整的。net 框架的一个轻量级的跨平台子集,可以在 Windows、Linux 和 OS x 上使用。net Framework。预计它将在新的特性中超越。net Framework,这些新特性可能会回到。net Framework。

值得注意的是。net Core 不是 Windows 桌面开发人员或 ASP 的选项。 净 4 开发人员。 除了支持 ASP.NET Core web 应用的CoreCLR运行时,.NET Core 还包括。NET 本机运行时,这是专门用于 Windows 10 上的通用 Windows 应用

运行 ASP.NET Core 和。NET Core

总结一下,让我们关注一下运行 ASP 的以下好处。 .NET Core 上的 web 应用,除了它的跨平台支持:

  • 灵活性:使用。net Core, web 应用可以使用。net Core 框架的特定版本进行部署,这将允许您只使用它所需要的版本来部署每个应用
  • 性能:使用。net Core,由于其更低的内存占用和更快的启动时间,您将享受到性能上的好处

是否运行 ASP。 在完整的。NET 框架或新的。NET Core 中,您将享受到一个现代的应用框架,它使您轻松进入云部署,并通过动态编译促进更快的开发。

Visual Studio 2015 和 Visual Studio Code 有什么新变化?

在每个发布周期中,Visual Studio 都有几个不同的 sku 可用。 从 Visual Studio 2013 开始,微软为学生、开源开发人员和小型团队添加了一个社区版,作为专业版的免费替代品。 除了 Visual Studio 2015,微软还增加了一个名为Visual Studio code的跨平台代码编辑器。

对于开发者来说,以下是 Visual Studio 2015 的现有产品:

  • 社区版
  • 专业版
  • 企业版

您可能还记得 Visual Studio 以前的版本也包括高级版和终极版。 这两个版本已经合并到企业版中。

要了解 Visual Studio 的各个版本,你可以参考以下网址的比较表:

https://www.visualstudio.com/products/vs-2015-product-editions

社区版

在 Community Edition 之前,许多学生、独立开发人员和小型团队使用免费的 Express Edition。 然而,Express Edition 缺少许多 Pro 功能,比如扩展。 现在,通过 Community Edition,非企业开发人员可以获得用于跨平台应用开发的全功能 IDE。

更好的是,社区版为成千上万的 Visual Studio 扩展打开了大门。 如果你没有在Visual Studio Gallery中找到你需要的,你也可以创建你自己的扩展。

专业版和企业版

对于有更多需求的企业开发人员和专业团队,您可以从专业版或企业版中进行选择。 完整的 ide 的功能之外的社区版,专业版也给你进入CodeLens,Team Foundation Server(TFS),敏捷项目规划工具。 CodeLens 提供了对代码历史的更深入的了解,而 TFS 可以用于源代码控制和持续集成。

企业版提供了上述所有功能,以及用于软件架构、建模、测试和代码覆盖的企业级工具。

要详细了解 Visual Studio 的各个版本,您可以参考https://www.visualstudio.com/products/compare-visual-studio-2015-products-vs中的比较表。

Visual Studio 代码

为了给今天的开发者提供更多的选择,微软已经开始提供一个叫做 Visual Studio code 的跨平台代码编辑器。 这个新产品是免费的,适用于您所选择的平台:Windows、Mac OS X 和 Linux。

Visual Studio Code 主要是为 web 和云应用,如 ASP.NET web 应用或 Node.js 后端代码。 但你可以自由地将其用于其他用途,如 Unity 游戏开发和使用 c++、Java、PHP、Python、Ruby 等最流行的语言进行跨平台应用开发。

对于那些想知道的人来说,Visual Studio Code 与流行的Sublime Text有着惊人的相似之处,并且是它的一个很好的替代品。 下面的截图显示了 Visual Studio Code:

<graphics/4921_01_04.jpg>

Visual Studio 代码:project.json

有关其他语言的更多信息,请参考https://code.visualstudio.com/Docs/languages

所有这些版本的 Visual Studio 2015 和 Visual Studio Code 都可以用于 ASP.NET Core web 应用开发。 当你创建一个新项目在 Visual Studio 2015 中,您将看到项目模板为空项目,Web API 项目,的 Web 应用项目,如下面屏幕截图所示。 另一方面,Visual Studio Code 是基于文件/文件夹的(而不是基于项目/解决方案的),所以你可以通过打开一个包含支持项目的文件夹来打开一个项目的文件:

<graphics/4921_01_05.jpg>

除了 Visual Studio 之外,您还可以使用Yeoman来创建一个新的 ASP.NET 项目工作。 Yeoman 是一个脚手架工具,可以帮助你生成各种现代 web 应用,包括 ASP.NET。 欲了解更多关于约曼的信息,请访问其网站http://yeoman.io

本书将主要关注 Visual Studio 2015。 所有的截图和说明都将使用 Visual Studio 2015 Community Edition 和运行在 Windows 10 上的 Edge 网络浏览器。 如果使用不同的编辑器、操作系统或 web 浏览器,则必须在自己的环境中执行相同的步骤。 无论使用什么平台,应用代码都应该保持不变。

运行 ASP.NET Core 在 Windows, Mac OS X 和 Linux

ASP.NET Core,你现在可以在 Mac OS X 和 Linux 上开发和部署你的应用,除了 Windows。 如果您在很久以前使用过活动服务器页面(ASP),您可能会记得Chili! 软 ASP,一个第三方解决方案的 web 服务器插件,它允许 ASP 在 Solaris, Linux 和其他 Unix 平台上运行。 新的。net Core 远不止于此。

通过一个跨平台的运行时,它可以与你的 web 应用一起部署,. net Core 提供了来自微软的官方支持,以享受 ASP 的好处.NET 在您最喜欢的平台上。 使用前面提到的 Visual Studio Code,您还可以轻松地构建 ASP。 这些平台上的核心应用。

虽然这本书将主要涵盖 ASP。 下面的说明将帮助您在 OS X 和 Linux 上设置您的环境。

Windows 上的 NET Core

为 asp.net 设置开发环境.NET Core 在 Windows 上是相当简单的。 如果你已经安装了最新的 Web 开发工具 Visual Studio 2015 Update 3,那么你已经拥有了你所需要的。 新的 ASP.NET Core 模板足以让你入门。

如果您只是需要一台或多台开发机器上的基本代码编辑器,那么您也可以在 Windows 上使用 Visual Studio Code。 请注意,社区版仅适用于非企业客户,因此不能将其与新的专业版或企业版一起安装。

Mac OS X 上的 NET Core

要在 Mac OS X 上设置开发环境,可以从安装最新版本的 Visual Studio Code 开始。 您也可以安装 ASP.NET Core 的命令行。 这里有一个高层次的三步流程让你开始:

  1. 安装打开 SSL。
  2. 安装。net Core SDK。
  3. 安装 Visual Studio Code for OS X。

获取关于设置 ASP. net 的最新详细说明(和命令行说明)。 在 Mac OS X 上,你可以参考微软的官方指南https://www.microsoft.com/net/core#macos

Linux 下的 NET Core

在 Linux 上设置开发环境有点复杂。 如您所料,您可以从在 Linux 机器上安装 Visual Studio Code 开始。

要总结设置运行时的步骤,您必须执行以下操作:

  1. 安装先决条件,根据您的 Linux 版本可能有所不同。
  2. 安装。net Core SDK。
  3. 安装 Visual Studio Code for Linux。

获取关于设置 ASP 的最新详细说明.NET Core 在 Linux 上,你可以参考微软的官方指南,网址如下。 选择一个 Linux 发行版,可以在https://www.microsoft.com/net/core上查看关于这个特定发行版的更多细节,如 Red Hat、Ubuntu、Debian 和其他许多发行版。

总结

在本章中,我们已经对 ASP 进行了介绍.NET Core、。NET Framework 以及各种版本的 Visual Studio。 我们还了解了. net Core 的跨平台特性,并简要介绍了如何在各种操作系统上设置开发环境。

在下一章中,我们将学习如何构建你的第一个 ASP.NET Core web 应用在 Visual Studio 2015 上运行在 Windows 10 上。 我们将浏览项目模板,并剖析一个基本的 web 应用,以便更好地理解它的各个部分及其配置。

二、构建您的第一个 ASP.NET Core 应用

不管你是经验丰富的 ASP.NET 开发人员或对控制器方法有点生疏,最好的方法是在 ASP 上获得最新的速度.NET Core 使用了Hello World应用。 除了新的配置文件之外,还需要了解新的项目类型。

超越它对 IIS 或 IIS Express 的传统依赖,您的新的 ASP.NET web 应用也可以在没有 web 服务器的情况下自托管。 这种新模式是其跨平台抱负的基础。

在本章中,我们将讨论以下原则和概念,以帮助您熟悉 ASP 的基本结构.NET Core 应用:

  • 项目模板
  • 模型、视图和控制器
  • 网络配置

Visual Studio 2015 中的项目模板

在 Visual Studio 2015 中,让自己接触到新项目模板的最快方法就是开始使用它们。 ASP.NET Core,目前有三个项目模板可以使用。

启动 Visual Studio 2015,然后点击File|New|Project。 在Visual c#|Web模板中,选择一个 ASP 模板.NET Core Web 应用继续。 在 Core 1.0 版本中,有两个不同的版本:一个使用全新的。net Core 运行时,另一个使用完整的。net 框架,如下图所示:

<graphics/image_02_001.jpg>

在预发布版本中,有其他项目类型可以作为Web模板使用。 这些现在都列在。net Core 下面,如下所示:

  • ASP。 净的 Web 应用
  • 类库(包)
  • 控制台应用(包)

项目模板的 ASP.NET Core 1.0 创建了一个控制台应用,该应用在Program.cs文件中有一个Main方法作为其入口点。 这类似于您可能已经熟悉的其他控制台应用。 当你继续使用任何 ASP.NET Core 选项,迎接你的将是全新的 asp.net.NET Core 模板。 下面的屏幕截图显示了ASP 下可用的项目模板.NET Core 模板:

<graphics/image_02_002.jpg>

新模板如下:

  • Web API
  • Web 应用

您将注意到在新模板列表中没有 Web Forms。 正如在第一章中所提到的,ASP 入门。 asp.net Core,新的 ASP. NET Core NET 更喜欢 MVC 而不是 Web 表单,它在跨平台实现中避免使用 MVC。

空模板

使用一些较老版本 Visual Studio 的开发人员的一个常见抱怨是:Empty模板不够空。 结果,这些开发人员将以空的模板开始,只是开始剥离新创建项目的组件。

这在 Visual Studio 2013 中得到了改进,并在 Visual Studio 2015 中继续发挥预期的作用。 选择选项可以确保你拥有一个只够启动的基本项目,如下图所示:

<graphics/image_02_003.jpg>

在一个空的模板项目中,您可以识别以下项目:

  • 物业
  • 文献
  • wwwroot(web 根目录)
  • 依赖项(初始为空)
  • Program.cs(包含Main入口点方法)
  • 项目。 json(最小设置)
  • (关于 ASP. html 的信息) 净核心)
    *** Startup.cs:
    • ConfigureServices()
    • Configure()
    • Main()* 网络。 配置(仅用于 IIS 启动; 使用基于 json 的文件进行配置)**

**## Web API 模板

ASP.NET Web API 模板是由 asp.net 发布的.NET MVC 4 在 2012 年。 它让 ASP.NET 开发人员可以轻松构建供 web 或移动客户端使用的 HTTP 服务。 ASP.NET Core MVC,开发人员可以在 MVC 项目中构建 Web API 时享受更精简的体验。

Web API 模板是为您的 Web 项目创建 RESTful HTTP 服务的一个很好的起点。 选择 Web API 项目模板将比空模板提供更多信息。 一个 Web API 项目的结构如下图所示:

<graphics/image_02_004.jpg>

在一个 Web API 模板项目中,你可以识别以下项目:

  • (Project) Properties
    • 启动设置。 json
  • 文献
  • wwwroot(web 根目录)
  • 依赖项(初始为空)
  • Controllers folder
    • ValuesController.cs
  • app 设置 json(最小设置)
  • Program.cs(包含Main入口点方法)
  • 项目。 json(基本设置和引用)
  • (关于 ASP. html 的信息) 净核心)
    *** Startup.cs
    • 构造器
    • ConfigureServices()
    • Configure()**

**除了空模板之外,Web API 模板还有以下附加项:

  • ValuesController.cs
  • app 设置 json

Web 应用模板

与其他模板相比,Web Application 模板提供了更多的初始代码和内容。 这是学习 ASP 的来龙去路的一个很好的起点。 净的核心。 在使用此 web 模板时,单击Change Authentication按钮以包括Individual User Accounts作为您的初学者应用的身份验证类型。 Web Application 项目的结构如下图所示:

<graphics/image_02_005.jpg>

在 Web Site 模板项目中,您可以标识以下项目。 首先,在你的项目文件夹上方有一些顶级项目:

  • (Project) Properties
    • 启动设置。 json
  • 文献
  • wwwroot
    • css
    • 图像
    • js
    • lib
    • _references.js
    • 图标图标
  • Dependencies
    • Bower(适用于BootstrapjQuery等)

接下来,你的代码、MVC 组件和 DB 迁移有几个文件夹,如下所示:

  • Controllers folder
    • 每个控制器的类文件
  • Data
    • 用于初始迁移的 Migrations 子文件夹
    • DB 上下文快照
  • Models
    • ModelsViewModels
  • Services
    • 服务类,例如用于消息传递和电子邮件
  • Views
    • 视图组织在每个控制器的子文件夹中
    • 共同的观点
    • _ViewImports.cshtml(视图共享导入)
    • _ViewStart.cshtml(共享视图头)

最后,有几个 JSON 配置文件和几个.cs代码文件,如appsettings.jsonbundleconfig.jsProgram.csproject.jsonProject_Readme.htmlStartup.cs:

  • appsettings.json(app 设置,如连接字符串)
  • bundleconfig.json(捆绑和小型化配置)
  • Program.cs(入点用Main法)
  • project.json(项目设置,服务器端引用)
  • Project_Readme.html(关于 ASP 的信息。 净核心)
  • Startup.cs
    • 构造器
    • ConfigureServices()
    • Configure()
  • web.config(仅用于 IIS 启动; 使用基于 json 的文件进行配置)

您可能必须单击解决方案资源管理器中的显示所有文件图标,以查看最初可能隐藏的其他文件。

你好,ASP.NET -你的第一个 ASP。 网络应用

大多数编程书籍和教程都会帮助您开始使用 Hello World 应用。 这指的是一个简单的应用,它具有应用的所有基本元素,使其能够在您的环境中运行。 如果应用可以在屏幕上显示 Hello World,那么就成功地设置了它。

创建一个新的 ASP.NET web 应用项目,并选择本章前面描述的 Empty 模板。 这应该为您的 Hello World 应用提供一个基本模板。

写一篇文章

默认情况下,空模板包含一个带有Configure()方法的Startup.cs类。 该方法应该有一行代码将Hello World写入 HTTP 响应输出流,以便在浏览器中显示。 下面的代码是针对Configure()方法的:

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!"); 
    }); 
} 

通过启用静态文件、Identity、MVC 等,可以使用Configure()方法来配置 HTTP 请求管道。 它可以用于在Startup.cs类中设置默认路由,取代需要global.asax文件的情况。

注意,Configure()方法是在ConfigureServices()方法之后调用的,它可以用来添加各种服务,如实体框架、身份和 MVC。 这两个方法都由运行时调用。

要更改正在显示的文本,只需将Hello World!替换为Hello, ASP.NET Core!。 此文本更改在功能上与 Empty 模板提供的内容没有任何不同,但它确实向您公开了Startup类及其方法。

启动应用

要启动应用,请按键盘上的F5,或在Debug菜单中单击开始调试。 这应该会在默认的 web 浏览器中启动应用,如下图所示:

<graphics/image_02_006.jpg>

您可能还熟悉 Visual Studio 工具栏上的绿色Play按钮,它用于启动您的应用。 在 Visual Studio 2015 中,这个按钮提供了一些新的选择,如下图所示:

<graphics/image_02_007.jpg>

选择如下:

  • IIS Express:在默认浏览器中启动的默认选项
  • 内部 Web 主机:以项目名称命名
  • web、gen、ef、其他:各种命令,通过project.json文件进行配置
  • 使用浏览:更改默认浏览器或添加新浏览器

您可能已经注意到,在调试时可以选择不同的 web 浏览器。 只需浏览浏览器列表,选择不同的浏览器进行调试,如下图所示:

<graphics/image_02_008.jpg>

还可以在解决方案资源管理器中右键单击项目以访问其属性。 在项目属性面板中,单击Debug选项卡,进一步定制每个调试配置文件,如下图所示:

<graphics/image_02_009.jpg>

Web 文件和文件夹

现在让我们深入研究 Web Application 模板项目中的所有这些文件和文件夹,以了解它们的用途。 首先,我们将关注配置文件,从bower.json开始。

该 JSON 配置文件用于管理Bower依赖项。 它以一个依赖项列表开始,然后是每个依赖项的可选详细配置,如下面的截图所示:

<graphics/image_02_010.jpg>

你会注意到这和 Solution Explorer 面板中显示的 Bower 依赖列表是一样的,如下图所示:

<graphics/image_02_011.jpg>

接下来,让我们看一下appsettings.json,它是您的应用配置文件。 ASP.NET Core 中,这个新的 JSON 文件(在测试版中暂时称为config.json)取代了将设置存储在基于 xml 的web.config文件中的需要。 您可以在Startup.cs代码中指定配置文件。

你的设置文件可能看起来像这样:

{ 
  "ConnectionStrings": { 
    "DefaultConnection": "<YourDbConnString>" 
  }, 
  "Logging": { 
    "IncludeScopes": false, 
    "LogLevel": { 
      "Default": "Debug", 
      "System": "Information", 
      "Microsoft": "Information" 
    } 
  } 
} 

最后但并非最不重要的是,我们有project.json,这是一个 JSON 文件,包含特定于项目的信息和服务器端依赖关系。 更多信息请参见本章的捆绑和发布部分。

模型,视图和控制器-一个 MVC 刷新器

对于那些不熟悉 MVC 的人,这里有一个快速复习,也包括了新的 ASP 信息。 净的核心。 下图显示了一个简单的架构图,它代表了 MVC 软件架构模式:

<graphics/4921_02_15.jpg>

即使图中显示了每一项中的一个,图中也可以有多个模型、视图和控制器。 每个请求通过一个特定的控制器路由,以确定将在用户的 web 浏览器中显示的结果。

当微软第一次发布 ASP 时,MVC 本身并不是一个新的概念。 净 MVC。 但它立即为。net 开发人员引入了一种开发 web 应用的新方法。 对于早期采用者来说,Web Forms 的好处变得很明显:更清晰的关注点分离,更好的可测试性,以及可以定制的轻量级客户机输出。

一些开发人员由于各种原因没有离开 Web Forms:新的学习曲线、个人偏好、公司需求和许多其他原因。 展望未来,ASP。 由于跨平台。NET Core 不支持 Web 表单,因此 NET MVC 变得更加必要。 此外,ASP.NET Core 不像它的前辈那样依赖于System.Web

所以,如果你还没有看过 MVC,现在是一个很好的时机。

控制器

在某种程度上,控制器是 ASP 的心脏。 净 MVC 应用。 每个控制器根据匹配的路由负责处理用户请求。 控制器可以更新模型中的数据,然后选择一个视图返回给用户。

每个控制器都是基类Controller的子类,它位于Microsoft.AspNetCore.Mvc命名空间中。 这与以前版本的 ASP 的Controller类不同.NET,它位于System.Web.Mvc命名空间中。 事实上,Web API 控制器也使用了新的Controller基类。

在 MVC 中,每个控制器通常从其操作方法中返回一个IActionResult。 对于 web 应用项目,这可以是一个视图。 对于 Web API 项目,这可以是一组数据。 从控制器返回视图和结果是可能的。

型号

与前面一样,您的模型将包含项目的数据域。 每个模型类都可以在代码中表示实体,同时用方括号包围的属性进行修饰。 这种声明式语法还允许您在模型中添加验证规则。

模型的数据会受到控制器的影响。 通过将模型绑定到视图,每个视图将自动决定显示什么以及如何显示它。

为了更清晰的架构,您可以使用特定于视图的模型(或ViewModel)来绑定到视图。 对于通过实体框架反映数据库实体的模型,可以使用带有服务层的存储库模式。 这将让您拥有不必依赖数据库实体结构的 UI 元素。

看到第六章,使用实体框架与数据库进行交互的代码,实体框架的更多信息,一个对象关系映射(ORM**). net 应用的框架。**

视图

应用中的视图可能是 MVC 中最简单的部分。 每个视图代表 UI 层,产生将显示给最终用户的客户端 HTML、CSS 和 JavaScript。

视图存储在.cshtml文件中,可以在同一个文件中包含服务器端代码和客户端代码。 一个名为ViewBag的内置对象允许你存储自己的属性并在视图中显示它们。 对象及其属性可以通过控制器代码进行操作。

不必在服务器端代码和客户端代码之间来回切换,现在可以在视图中使用标记助手来实现更流畅的语法。 标签助手允许你在 HTML 标签中使用自定义属性,这可能是那些使用AngularJS的开发者所熟悉的。

参见第 3 章理解 MVC,了解更多关于标签助手和视图的信息。

使用 project.json 进行 Web 配置

project.json文件中,您可以找到以下信息:

  • userSecretsId:类似于 guide 的值,用于处理用户秘密
  • 依赖项:服务器端依赖项列表
  • 版本:项目版本
  • 框架:.NET Core 框架名称和版本
  • 构建/运行时/发布选项:构建/运行时配置和发布 web 应用时包含的文件/文件夹列表
  • 脚本:可以由特定事件(如prepublishpostpublish和其他事件)触发的操作的脚本列表

下面的project.json文件截图显示了一个典型的项目配置文件的内容,折叠起来适合所有顶级项目:

<graphics/image_02_013.jpg>

依赖和框架

在配置文件的依赖项部分,您将发现所有服务器端依赖项的列表,例如 ASP.NET MVC,实体框架等等。 它们在解决方案资源管理器中也可以作为项目引用可见。

<graphics/image_02_014.jpg>

前面的屏幕截图显示了依赖项部分的扩展,以显示引用及其版本号。 下面的截图显示了解决方案资源管理器中相同的一组引用:

<graphics/image_02_015.jpg>

命令和工具

预发布版本的 ASP.NET Core 包含了可以在project.json配置文件中配置并在 Visual Studio IDE 中触发的命令。 下面的屏幕截图显示了配置文件的命令部分:

<graphics/image_02_016.jpg>

ASP 不再支持commands部分。 1.0 NET Core。 相反,在project.json文件中有一个新的tools部分,它可以用来指定包含项目工具的包。

捆绑发布

最后,我们还将在部署应用时包含用于发布的特定组件。 下面的屏幕截图显示了publishOptions部分,展开显示了要包含的组件:

<graphics/image_02_017.jpg>

总结

在本章中,我们已经了解了 ASP 的基本结构.NET Core 1.0 web 应用。 我们深入研究了组成应用的各个部分,包括全新的配置文件。 我们还介绍了 MVC 及其组件的基础知识。

在下一章中,我们将深入探讨 ASP.NET Core MVC。 我们将从头构建一个示例应用,以演示 ASP 中模型、视图和控制器的特性.NET Core MVC web 应用。****

三、理解 MVC

在前一章中,我们快速回顾了 ASP.NET 中的 MVC 及其组件。 在本章中,我们将深入探讨 ASP 中的 MVC.NET Core,它是 beta 版的 MVC 6。

开发人员常见的两个问题是:如何将旧的 MVC 项目升级到 ASP.NET Core MVC ? 是否存在自动迁移过程? 从 MVC 5 迁移到 asp.net 中新的 MVC.NET Core 涉及一些手动步骤,因为没有自动迁移过程。 您可以将所有静态客户端文件复制到wwwroot位置,并调整对这些文件的任何引用以指向正确的位置。

对于服务器端代码,您可以在您的模型、视图和控制器上进行迁移,而无需进行很多更改。 本章将涵盖以下各方面的知识:

  • 控制器
  • 的观点
  • 模型

对于已经使用过以前版本的 ASP 的开发人员来说,本章的部分内容会比较熟悉。 净 MVC。 我们将浏览一些熟悉的材料,同时介绍对 MVC 的更新添加。

建筑控制器

您的 MVC 控制器是奇迹发生的地方。 请求来自最终用户,然后返回内容和数据。 在这两者之间会发生什么取决于你——开发者。

控制器方法

默认情况下,控制器方法可以使用[HttpGet]属性用于 HTTPGET请求,或者完全忽略这个动作谓词属性,因为它是默认行为。 很可能,您已经使用了以下 HTTPGETPOST动词:

  • HttpGet:使用 HTTPGET方法,带有可选的querystring参数
  • HttpPut:使用 HTTPPOST方法提交表单,创建实体

除了上述内容,您还应该注意可以用作控制器属性的其他 HTTP 谓词; 它们如下:

  • HttpPut:使用 HTTPPUT方法编辑现有实体
  • HttpDelete:使用 HTTPDELETE方法删除已有实体
  • HttpPatch:允许部分模型更新,而不是完整的PUT请求
  • AcceptVerbs:允许指定多个动作动词

基本控制器

使用 Visual Studio,您可以添加一个基本控制器,并逐步向其添加代码。 您还可以使用 scaffolding 添加一个更完整的控制器,其中包括模型绑定和操作方法来操作模型。 但我们会在本章的后面讲到。

首先,让我们创建一个示例项目,我们将在其中添加一个基本控制器,如下所示:

  1. 创建一个新的 ASP。 通过点击文件|新建|项目
  2. 选择ASP.NET Web 应用(.NET Core)
  3. 命名您的项目患者记录
  4. ASP. net 列表下选择Web 应用**.NET Core 模板**。
  5. 点击更改认证切换为个人用户账号
  6. 点击OK创建您的 web 项目。

我们也可以从一个空的模板开始,但是这样我们就必须添加更多的依赖项和配置才能启动和运行。 让我们继续添加基本控制器。

**要添加基本控制器,请执行以下步骤:

  1. 在“解决方案资源管理器”中右键单击“Controllers”文件夹。
  2. 在上下文菜单中,单击添加|新项目
  3. 在。net Core 和 ASP.NET 下的Add New Item对话框中,选择MVC Controller Class
  4. 将控制器命名为PatientController,单击添加继续操作。

以下截图显示了添加新项目窗口:

<graphics/image_03_001.jpg>

此时,您应该拥有一个带有一个Index()方法的基本控制器,该方法返回一个简单的View。 这对于有经验的 ASP 应该已经很熟悉了。 净 MVC 开发人员。 如果我们现在运行项目,web 应用应该在 web 浏览器中启动,使用任意端口号,比如12345。 您的端口号会有所不同。 您的 web 应用的链接类似于http://localhost:12345

在浏览器仍然打开的情况下,您可以尝试通过将控制器名称Patient添加到 URL:http://localhost:12345/Patient的末尾来访问PatientController

这将导致未处理的InvalidOperationException,因为我们还没有为Patient控制器添加Index视图。 与以前版本的 MVC 一样,该视图通常位于Views文件夹中名为Patient的子文件夹中。 如果没有,回退视图将位于Shared子文件夹和Views文件夹中。 当这两个常规位置都不包含预期的视图时,就会发生异常。

为了绕过预期的路径,让我们用以下代码替换PatientController类的Index方法:

public string Index() 
{ 
    return "Patient Info"; 
} 

注意,我们已经将返回类型改为string,这样我们就可以返回一个字符串字面值来测试控制器。 如果你再次运行应用,当你在 http://localhost:12345/Patient访问控制器Patient时,你现在应该能够在浏览器中看到占位符文本:

<graphics/image_03_002.jpg>

URL 路由和约定

如果你看一下Startup.cs中的Configure()方法,你可以看到你的 web 应用的默认路由:

app.UseMvc(routes => 
{ 
    routes.MapRoute( 
        name: "default", 
        template: "{controller=Home}/{action=Index}/{id?}"); 
}); 

你可能还记得第二章构建你的第一个 ASP。 asp.NET Core 应用,即在 asp.net 中采用Configure()方法.NET Core 用于应用在ConfigureServices()方法中添加的组件和服务。 从示例代码中可以看到,控制器和操作值分别默认为HomeIndex

可以选择将id参数添加到 URL 的末尾斜杠之后。 注意,这与向QueryString添加id参数不同,但两种方法都可以通过方法参数将值传递给控制器方法。

为了使用Encode()方法,请确保您已经添加了以下using语句以在代码中包含WebEncoders命名空间:

using System.Text.Encodings.Web; 

为了使用默认约定,将PatientController类中的Index方法更新如下以接受参数:

public string Index(int id, string name = "Unknown") 
{ 
    return "Patient Info: " + HtmlEncoder.Default.Encode( 
        "ID: " + id + ", " + 
        "Name: " + name); 
} 

参数idname分别表示患者的 ID 和姓名。 如果没有指定名称,则name参数默认为"Unknown"。 传递的值被封装在对Encode()的调用中,以确保没有恶意标记或脚本通过QueryString传递。

您现在应该能够使用http://localhost:12345/Patient?id=1&name=John作为QueryString参数。 下面的截图是相同的输出:

<graphics/image_03_003.jpg>

实施视图

MVC 中的视图构成了表示层,这是一个用户界面,它保存着供用户交互的屏幕元素。 任何 web 应用的 UI 都可能很快变得非常繁忙,要么同时充满了太多的条目,要么承载了业务逻辑和不必要的代码。 MVC 的关注点分离的目标是帮助开发人员创建架构良好的应用,其中视图是轻量级的,验证在模型层中执行,模型层通过绑定与视图连接。

基本观点

与添加基本控制器的方式类似,我们将创建一个基本视图并逐步向其添加代码。 正如您可以使用 scaffolding 创建一个更完整的控制器一样,您也可以创建一个附加到模板和模型的更完整的视图。 但是同样的,我们会在本章的后面讲到。

首先,让我们为Patient控制器使用的视图创建一个子文件夹,这样我们就可以将我们的新视图添加到其中。 遵循以下步骤:

  1. 在“解决方案资源管理器”中,右键单击Views文件夹,并向其中添加一个新文件夹。
  2. 将子文件夹命名为Patient,以利用命名约定。
  3. 右键单击Patient子文件夹,然后单击添加|新建项目
  4. 添加新项目对话框中,选择ASP 下的MVC 视图页面**。** 。
  5. 将视图命名为Index.cshtml,然后单击添加继续。

我们使用默认视图名Index.cshtml,这样这个视图将由Patient控制器中的Index()控制器方法返回。 此时,视图没有实际的内容,只有一些占位符符号用于注释和服务器端代码。 代码如下:

@* server-side comments *@ 
@{ // server-side code } 

用以下内容替换视图的内容:

@{ 
    ViewData["Title"] = "Patient Index"; 
} 
<h2>Patient Index</h2> 

"Title"ViewData值由默认的_Layout.cshtml布局文件使用,该文件可以在Views文件夹中的Shared子文件夹中找到。 以下代码适用于Patient控制器的Index视图:

<title>@ViewData["Title"] - PatientRecordsWebApp</title> 

用以下代码替换控制器的Patient视图:

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

要浏览此页面,请运行应用并将Patient控制器名称添加到 URL 末尾的斜杠后面,如http://localhost:12345/Patient

您现在应该在浏览器中看到视图的内容,包括标题和页眉文本。 如下截图所示:

<graphics/image_03_004.jpg>

视图中的标签助手

为了更容易地浏览到这个页面,让我们更新它的布局文件,以包含一个到controller方法的链接,该方法将返回这个视图。 首先,在布局文件中找到一组可点击链接,<li>列出<ul>无序列表中的项目。

请注意,<a>标记每个都有两个属性作为标记助手:

  • asp-controller
  • asp-action

标签助手是 ASP 中新引入的.NET Core MVC,并且类似于您过去可能使用过的HtmlHelpers。 这两个属性的值将决定控制器名称以及单击链接时将触发的后续操作方法。

让我们为Patient控制器添加一个附加的可点击链接,就在Contact链接之后,使用以下代码:

<li><a asp-controller="Patient" asp-action="Index">Patients</a></li> 

运行 web 应用来查看顶部标题区域的新链接,这将允许您更快地跳转到患者的索引视图:

<graphics/image_03_005.jpg>

在本章的后面,我们将学习如何在视图中使用标记助手来进行验证。 我们还将向模型中添加特定的属性,以帮助在提交表单时验证特定的字段。

ViewData、ViewBag 和 TempData

通过在控制器中使用ViewData项设置值,然后在视图中检索值,可以将数据从控制器传递到视图。 这些值被存储为具有基于字符串的键的键值字典项。 与使用ViewData相比,ViewBag是一种更动态的选择,允许您在不进行类型转换的情况下使用复杂数据类型。 赋值将在重定向时重置。

下面是如何在控制器中使用ViewDataViewBag的两个例子:

ViewData["PatientId"] = id; 
ViewBag.PatientData = "someData"; 

TempData略有不同,因为它在重定向期间保留其数据,这允许您在重定向操作期间在控制器之间传递数据。 它的语法类似于ViewData,所以它可以作为一个字典项使用,具有以下基于字符串的键:

TempData["UserToken"] = userTokenData; 

让我们在Patient控制器中添加以下Details()方法,为ViewData对象赋值:

public IActionResult Details(int id, string name = "Unknown") 
{ 
    ViewData["PatientId"] = id; 
    ViewData["PatientName"] = name;  
    return View(); 
} 

这里,我们分别为患者的 ID 和名称设置了两个ViewData值。 为了在视图中显示数据,我们将添加一个新的Details视图,如下所示:

  1. 在“解决方案资源管理器”中展开Views文件夹。
  2. 右键单击Patient子文件夹,然后单击添加|新建项目
  3. 添加新项目对话框中,选择ASP 下的MVC 视图页面**。** 。
  4. 命名您的视图Details.cshtml以便继续。

用以下代码替换Details视图的内容:

@{ 
    ViewData["Title"] = "Patient Details"; 
} 
<h2>Patient Details</h2> 
<ul> 
    <li>ID: @ViewData["PatientId"]</li> 
    <li>Name: @ViewData["PatientName"]</li> 
</ul> 

为了提供Index视图和Details视图之间的简单链接,我们还将更新位于Views文件夹中Patient子文件夹中的Index视图。

用以下代码替换控制器Patient``Index视图的内容:

@{ 
    ViewData["Title"] = "Patient Index"; 
} 
<h2>Patient Index, with Tag Helpers</h2> 

<ul> 
    @for (int i = 0; i < 10; i++) 
    { 
        <li><a asp-controller="Patient" asp-action="Details"  
               asp-route-id="@i" asp-route-name="Patient @i"> 
               Patient # @i</a></li> 
    } 

</ul> 

在前面的代码中,for循环用于生成可单击链接的列表。 点击每个链接可以显示特定患者的详细信息。 同样,您可以在<a>标记中看到以下标记帮助器属性的使用:

  • asp-controller
  • asp-action
  • asp-route-id
  • asp-route-name

最后两个属性足够开放,可以引用 ID 和 name 等命名参数。 id属性将自动遵循 URL 路由约定,而name属性将作为 QueryString 参数添加。

连结将以下列格式显示:

  • http://localhost:12345/Patient/Details/0?name=Patient%200
  • http://localhost:12345/Patient/Details/1?name=Patient%201
  • http://localhost:12345/Patient/Details/2?name=Patient%202

问号前面的数字值是由为应用定义的 URL 路由定义的 ID 值。 注意,参数值中的空格是 url 编码为%20的。

运行 web 应用,单击顶部工具栏中的Patients链接,导航到Patient索引页。 在下面的截图中,你会看到一个包含 10 个项目的列表,每个项目都有自己的链接。 单击其中的一个链接进入该特定患者的Details页面。 详情页面将显示选定患者的 ID 和姓名:

<graphics/image_03_006.jpg>

设计模型和 ViewModels

您可以使用模型来存储一组数据,而不是将单个值从控制器逐个传递到视图。 控制器负责更新模型,模型可以与视图关联以获取其数据。

创建模型

模型只是一个文件扩展名为.cs的类文件。 在解决方案资源管理器面板中,您可以将新的模型类文件添加到Models文件夹中。 您可能已经注意到,对于 MVCController类和 MVCView页有一些选择,但是对于Model类没有选择。

要创建一个模型类,我们可以在添加新项目时选择class选项,如下所示:

  1. 在“解决方案资源管理器”中,右键单击Models文件夹,然后单击添加|新项目
  2. Add New Item对话框中,选择Code下的Class
  3. 将文件命名为Human.cs以创建一个新模型。
  4. 验证您有一个名为Human的空类。

Human类中添加以下字段:

public class Human 
{ 
    public int ID { get; set; } 
    public string SocialSecurityNumber { get; set; } 
    public DateTime DateOfBirth { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

您可能还注意到在下面的截图中,在Models文件夹中有ViewModels子文件夹。 当您将视图绑定到模型时,模型中定义的字段表示关联视图中的 UI 元素和表单字段。 这些子文件夹是组织这些模型的好地方,它们的名称与你的控制器名称相匹配:

<graphics/4921_03_07.jpg>

绑定模型到视图

要将视图绑定到模型,可以在视图的.cshtml文件中看到以下语法:

@model MyModelName 

视图的其余部分应该包含一个服务器端表单,以及与模型字段关联的表单元素。 虽然在一个视图中可能有多个表单,但如果可以避免多个表单,MVC 视图通常倾向于使用一个表单。 在任何情况下,用于视图的模型都应该包含所有必要的字段,以覆盖视图中的所有表单。

在以前的版本中.NET MVC,你可能已经为服务器端表单使用了以下语法:

@using (Html.BeginForm("action", "controller", FormMethod.Post, new {})) 
{ 
    @Html.LabelFor(m => m.Field1) 
    @Html.TextBoxFor(m => m.Field1) 

    @Html.LabelFor(m => m.Field2) 
    @Html.TextBoxFor(m => m.Field2) 

    <input type='Submit' value='Submit' /> 
} 

在 ASP.NET Core MVC,下面介绍了使用标记助手的语法:

<form asp-controller="controller" asp-action="action" method="post"> 
    <label asp-for="Field1"></label> 
    <input asp-for="Field1" /> 
    <label asp-for="Field2"></label> 
    <input asp-for="Field2" /> 
    <input type="submit" value="Submit" /> 
</form> 

这种新方法也使代码更干净、更高效。 当表单被提交时,控制器方法可以接受模型的数据类型作为参数来接收它的所有字段:

[HttpPost] 
public IActionResult MyAction(MyModelName model) 
{ 
    return View(model); 
} 

ViewModels 和映射

当您在它们自己的文件夹中组织您的ViewModels时,您通常会将每个视图绑定到一个特定的ViewModel。 但是,数据库设计可能需要在代码中定义实体作为与数据库对象匹配的模型文件。 您需要弄清楚如何将特定于数据库的模型映射到您的ViewModels

有几种不同的方法可以映射你的ViewModels和数据库实体模型:

  • 当您的控制器方法接受一个ViewModel时,您可以逐个将每个字段映射到它们对应的实体模型字段
  • 您可以使用像AutoMapper这样的库,它可以在 GitHub/NuGet 上免费获得,并在http://automapper.org中描述为基于约定的基于对象的映射器

为了更深入地了解实体模型,我们将在第 6 章中介绍对象关系映射和实体框架,在代码中使用实体框架与数据库交互。

把它结合在一起

为了把它们结合在一起,让我们利用 Visual Studio 内置的代码生成特性来利用脚手架和绑定。 在本节中,我们将讨论帮助模型验证的字段属性。

在结束本章之前,我们还将学习如何使用异常处理来捕获代码中的错误。

脚手架、验证和模型绑定

使用到目前为止构建的PatientRecords项目,让我们按照以下步骤向其添加一个新控制器,以利用 scaffolding。 而不是点击添加项目,我们将选择控制器选项:

  1. 在解决方案资源管理器中,右键单击Controllers文件夹。
  2. 在上下文菜单中,单击添加|控制器
  3. 选择使用 EF 添加带有视图的新 MVC 控制器的选项。

在添加控制器时,系统将提示您输入其他信息。 选择/输入以下信息:

  • 模型类:Human,来自您的模型名称空间
  • 数据上下文类:ApplicationDbContext
  • 控制器名称:HumanController

对于以下所有的复选框,你可以保持默认值不变:

  • 生成视图:默认选中,用于为每个动作生成相应的视图。
  • 引用脚本库:默认选中,包含对客户端代码中的脚本库的引用。
  • 使用布局页面:默认选中,允许输入布局名称,或者可以为空以允许_viewstart.cshtml被使用。 这个页面通常包含一个对项目默认布局页面的引用,默认设置为_Layout

您可能已经注意到,控制器名称默认为HumenController,其中有一个e。 这是因为脚手架工具试图将代码中的实体多元化,所以它错误地假设Human的复数形式是Humen。 要修复此问题,请确保在添加控制器之前用a将其重命名为HumanController

在添加了搭建的控制器之后,您可以检查HumanController的内容,以验证它是否为您自动生成了一些代码。 它应该从一个数据库上下文对象开始,然后是一个利用该上下文的构造函数。

类的其余部分应该有一系列用于基本 CRUD 操作的操作方法,即用于创建、读取、更新和删除条目的操作:

  • 索引:Human对象列表
  • Details(id):具体Human对象的详细信息
  • Create:GET/POST 方法显示创建表单并创建新实体
  • Edit:GET/POST 方法来显示编辑表单并编辑现有实体
  • Delete:GET/POST 方法,显示确认界面,执行删除操作

查看Views文件夹,并验证是否有一个Human子文件夹,其中包含前面所有操作方法的单独视图:创建、删除、详细信息、编辑和索引。 如果您打开这些.cshtml文件中的任何一个,您将在每个视图的第一行中找到对每个对应模型的引用。

这些视图中包含的验证使用新的标记助手语法。 这些标记可以用于验证,我们在前一节中看到了这一点。 在此基础上,我们可以编辑Human模型,以包含一些属性来帮助验证。

你需要的属性定义在DataAnnotations命名空间中,所以你应该确保以下 using 语句被添加到你的Human.cs文件中:

using System.ComponentModel.DataAnnotations; 

编辑Models目录下的Human.cs文件,以包含以下字段的属性:

public class Human 
{ 
    public int ID { get; set; } 
    [Required] 
    [StringLength(11)] 
    [Display(Name = "SSN")] 
    public string SocialSecurityNumber { get; set; } 
    [Display(Name = "DOB")] 
    [DataType(DataType.Date)] 
    public DateTime DateOfBirth { get; set; } 
    [Display(Name = "First Name")] 
    public string FirstName { get; set; } 
    [Display(Name = "Last Name")] 
    public string LastName { get; set; } 
} 

这里使用了以下属性:

  • Required:必填项
  • StringLength(n):限制字段值为 n 个字符
  • Display(Name ="Alt Name"):在用户界面中显示的备用名称
  • :限制字段为特定的数据类型,例如 date

注意事项

如果您想试验其他属性,请参考 ASP.NET 文档来查找此名称空间中的其他验证属性。

在再次启动 web 应用之前,让我们添加一个到Human控制器Index视图的新链接。 我们可以在Views/Shared目录下_Layout.cshtml的顶部菜单中添加另一个可点击的链接:

<li><a asp-controller="Human" asp-action="Index">Humans</a></li> 

前面的行可以添加到前面添加的Patients链接之后。 如果此时单击顶部工具栏中的Humans链接,您将得到一个错误,因为我们的数据库还不存在。

数据库设置和数据录入

要设置初始数据库,我们必须从命令提示符运行初始迁移。 当前文件夹必须设置为项目的根位置,即Startup.cs所在的位置。 这与您的ModelsViewsControllers文件夹所在的位置相同。

打开文件夹所在位置的命令提示符后,可以运行以下命令。 您的 DNVM 版本可能会有所不同:

dotnet restore
dotnet build
dotnet ef migrations add Initial
dotnet ef database update

以上命令的作用如下:

  • restore:为你的项目恢复包
  • :编译并构建您的项目
  • :创建数据库模型的初始快照
  • 创建/更新您的数据库

Visual Studio 应该为你安装dotnet工具,所以你可以参考第一章ASP 入门.NET Core,用于初始设置说明,如果您遗漏了任何内容。 关于实体框架的更深入的介绍,请参见第 6 章在代码中使用实体框架与数据库交互

命令运行完成后,您应该拥有数据库的初始版本,以及与实体模型相匹配的必要数据库表,例如Human表。 Human表中的列应该匹配Human.cs模型文件中的字段。

在 Visual Studio 中查看 SQL Server 对象资源管理器,在顶部菜单中选择view|SQL Server 对象资源管理器,如下图所示:

<graphics/4921_03_08.jpg>

现在,您可以再次运行应用,并单击顶部工具栏上的Humans链接。 这应该会把你带到Index视图,显示你还没有Humans视图,如下截图所示:

<graphics/image_03_009.jpg>

单击Create New链接创建一个新的Human表项。 单击此链接将带您进入Human控制器的Create视图。 输入一些值,然后点击Create按钮,如下截图所示:

<graphics/image_03_010.jpg>

一旦创建了新的Human条目,您的提交将由后版本的Create方法处理。 如果您遗漏了任何必需的值或输入了错误的字符数,验证消息将自动显示在 UI 中。 正确提交后,你会被带回到Index视图,在那里你会看到你刚刚创建的新Human条目,如下截图所示:

<graphics/image_03_011.jpg>

异常处理

在 ASP.NET Core MVC 中,异常处理已经得到了发展,并且出现了处理异常的新方法。 UseDeveloperExceptionPage()UseExceptionHandler()的使用可以在 ASP 中看到。 净 web 应用。 要查找这些方法调用的位置,只需查看Startup.cs文件即可。 在Configure()方法内部,你可以找到对以下方法的调用:

app.UseDeveloperExceptionPage(); 
app.UseExceptionHandler("/Home/Error"); 

当您在开发中运行应用时,第一个方法调用是相关的,因此您可以获得额外的调试信息。 在生产环境中,实际的异常处理程序将用于重定向到适当的错误页面。 上述代码触发控制器的HomeError动作方法,然后触发控制器的Error视图。 在我们的样例应用中,在Shared文件夹中有一个Error.cshtml文件,在生产环境中出现异常时将使用该文件。

为了模拟开发和生产环境,可以将环境变量ASPNETCORE_ENVIRONMENT的值更改为DevelopmentProduction。 此更改可以在您的launchSettings.json文件中更改,也可以在项目属性屏幕的Debug标签中更改。

与以前的版本一样.NET,您应该使用 try/catch 块来预测在运行时可能发生的各种异常,并适当地处理它们。 在某些情况下,您可能不得不在应用代码中抛出异常,以便让调用方法处理异常。

总结

在本章中,我们已经了解了模型、视图和控制器如何结合在一起形成一个可工作的 ASP.NET Core MVC web 应用。 我们接触了数据库设置,并以异常处理结束。

在下一章中,我们将学习 Web api,以及如何使用 ASP.NET 超越传统的 Web 应用。 我们将看看可以利用 Web API 后端的各种客户机。**

四、使用 Web api 扩展您的应用

如果你用过 ASP。 asp.net Web API 的早期版本.NET,您可能还记得 Web API 控制器通常继承自APIController。 这在 ASP 中已经改变.NET Core,作为 MVC 和 Web API 统一的一部分。 因此,每个 Web API 控制器都继承自Controller类,它也是每个 MVC 控制器的基类。

在本章中,我们将完成一个 Web API 项目的工作示例。 在本章中,我们将涵盖以下内容:

  • Web api
  • Web API 配置
  • Web API 的路线
  • 使用 Web API 应用

了解 Web API

构建 web 应用可能是一种有益的体验。 接触到广泛的潜在用户所带来的满足感可以胜过花在微调应用和修复 bug 上的令人沮丧的夜晚。 但有些手机用户要求只有原生手机应用才能提供更流畅的体验。

移动浏览器在低带宽的情况下可能会遇到性能问题,在这种情况下,HTML5 应用只能在服务器端后台很重的情况下发挥作用。 Web API 及其 RESTful 端点是用对移动友好的服务器端代码构建的。

Web api 的例子

为了创建一个软件,多年的智慧告诉我们,我们在构建软件时应该考虑用户。 如果没有用例,它的特性实际上毫无用处。 通过围绕用户故事设计特性,揭示与用户操作直接相关的公共端点是有意义的。 因此,您最终将得到一个为更多用户工作的更精简的 web 应用。

如果你需要更多的说服力,这里是一个 Web API 的特性和好处的概述:

  • 它允许您构建现代的轻量级 web 服务,只要您不需要 SOAP,这对您的应用来说是一个很好的选择
  • 使用它比以往任何使用 ASP 完成的工作都要容易.NETWindows Communication Foundation(WCF)服务
  • 它支持 RESTful 端点
  • 它适用于各种客户端,包括移动端和网络端
  • 与 ASP 统一.NET MVC,可以包含/不包含您的 web 应用

从零开始创建新的 Web API 项目

让我们构建一个名为Patient Records的示例 web 应用。 在这个应用中,我们将从头创建一个 Web API 来允许以下任务:

  • 增加一个新病人
  • 编辑现有患者
  • 删除现有患者
  • 查看特定患者或患者列表

这四个操作构成了我们系统中所谓的 CRUD 操作:创建、读取、更新或删除患者记录。

按照下面的步骤,我们将在 Visual Studio 2015 中创建一个新项目:

  1. 创建一个新的 Web API 项目。
  2. 添加 API 控制器。
  3. 为 CRUD 操作添加方法。

前面的步骤已经扩展为详细的说明,如下截图:

  1. In Visual Studio 2015, click File | New | Project. You can also press Ctrl + Shift + N on your keyboard.

    <graphics/image_04_001.jpg>

  2. On the left panel, locate the Web node below Visual C#, then select ASP.NET Core Web Application (.NET Core), as shown in the following screenshot:

    <graphics/image_04_002.jpg>

  3. With this project template selected, type in a name for your project, for example PatientRecordsApi, and choose a location on your computer, as shown in the following screenshot:

    <graphics/image_04_003.jpg>

  4. 您还可以选择右下角的复选框为您的解决方案文件创建一个目录,并/或将您的新项目添加到源代码控制中。 点击OK继续。

  5. In the dialog that follows, select Empty from the list of the ASP.NET Core Templates, then click OK, as shown in the following screenshot:

    <graphics/image_04_004.jpg>

  6. 或者,您可以选中Microsoft Azure的复选框,将您的项目托管在云中。 点击确定继续。

构建您的 Web API 项目

在解决方案资源管理器中,您可能会看到正在恢复您的引用。 这发生在每次你创建一个新项目或添加新的引用到你的项目必须通过NuGet恢复,如下截图所示:

<graphics/image_04_005.jpg>

遵循以下步骤,修复您的引用,并构建您的 Web API 项目:

  1. Right click on your project, and click Add | New Folder to add a new folder, as shown in the following screenshot:

    <graphics/image_04_006.jpg>

  2. Perform the preceding step three times to create new folders for your Controllers, Models, and Views, as shown in the following screenshot:

    <graphics/image_04_007.jpg>

  3. Right click on your Controllers folder, then click Add | New Item to create a new API controller for patient records on your system, as shown in the following screenshot:

    <graphics/image_04_008.jpg>

  4. In the dialog box that appears, choose Web API Controller Class from the list of options under .NET Core, as shown in the following screenshot:

    <graphics/image_04_009.jpg>

  5. 命名您的新 API 控制器,例如PatientController.cs,然后单击添加继续。

  6. In your new PatientController, you will most likely have several areas highlighted with red squiggly lines due to a lack of necessary dependencies, as shown in the following screenshot. As a result, you won’t be able to build your project/solution at this time:

    <graphics/image_04_010.jpg>

在下一节中,我们将学习如何配置您的 Web API,以便它在配置文件中具有适当的引用和依赖项。

在 Web 应用中配置 Web API

当一个特定的 URL 被请求时,web 服务器如何知道向浏览器发送什么? 答案在于您的 Web API 项目的配置。

设置依赖项

在本节中,我们将学习如何使用 IDE 自动设置依赖项,或者通过编辑项目的配置文件手动设置依赖项:

  1. To pull in the necessary dependencies, you may right-click on the using statement for Microsoft.AspNet.Mvc and select Quick Actions and Refactorings…. This can also be triggered by pressing Ctrl + . (period) on your keyboard or simply by hovering over the underlined term, as shown in the following screenshot:

    <graphics/image_04_011.jpg>

  2. Visual Studio should offer you several possible options, from which you can select the one that adds the package Microsoft.AspNetCore.Mvc.Core for the namespace Microsoft.AspNetCore.Mvc. For the Controller class, add a reference for the Microsoft.AspNetCore.Mvc.ViewFeatures package, as shown in the following screenshot:

    <graphics/image_04_012.jpg>

    添加 Microsoft.AspNetCore.Mvc.Core 1.0.0 包

  3. If you select the latest version that’s available, this should update your references and remove the red squiggly lines, as shown in the following screenshot:

    <graphics/image_04_013.jpg>

    更新您的参考资料,并删除红色的波浪线

  4. The preceding step should automatically update your project.json file with the correct dependencies for the Microsoft.AspNetCore.Mvc.Core, and Microsoft.AspNetCore.Mvc.ViewFeatures, as shown in the following screenshot:

    <graphics/image_04_014.jpg>

  5. The “frameworks” section of the project.json file identifies the type and version of the .NET Framework that your web app is using, for example netcoreapp1.0 for the 1.0 version of .NET Core. You will see something similar in your project, as shown in the following screenshot:

    <graphics/image_04_015.jpg>

  6. Click the Build Solution button from the top menu/toolbar. Depending on how you have your shortcuts set up, you may press Ctrl + Shift + B or press F6 on your keyboard to build the solution. You should now be able to build your project/solution without errors, as shown in the following screenshot:

    <graphics/image_04_016.jpg>

在运行 Web API 项目之前,打开Startup.cs类文件,用Configure()方法中的app.UseMvc()调用替换app.Run()语句/块(及其内容)。 要将Mvc添加到项目中,请在ConfigureServices()方法中添加对services.AddMvcCore()的调用。 要编译此代码,请添加对Microsoft.AspNetCore.Mvc的引用。

Web API 项目的一部分

让我们来仔细看看PatientController这门课。 自动生成的类有以下方法:

  • public IEnumerable<string> Get()
  • public string Get(int id)
  • public void Post([FromBody]string value)
  • public void Put(int id, [FromBody]string value)
  • public void Delete(int id)

Get()方法只是返回一个JSON对象作为一个可枚举的值字符串,而Get(int id)方法是一个覆盖的变量,它为指定的 ID 获取特定的值。

Post()Put()方法可用于创建和更新实体。 请注意,Put()方法将 ID 值作为第一个参数,以便它知道要更新哪个实体。

最后,我们有Delete()方法,可以使用该方法删除使用指定 ID 的实体。

这些操作将工作最好与一个对象-关系映射(ORM)框架(如实体框架,我们将在第六章、【显示】使用实体框架与数据库进行交互的代码。 同时,我们将在 API 控制器代码中创建占位符对象和值。

**## 运行 Web API 项目

你可以在一个可以显示 JSON 数据的 Web 浏览器中运行 Web API 项目。

如果你使用谷歌 Chrome 浏览器,我建议使用JSONView 扩展(或其他类似的扩展)正确显示 JSON 数据。

上述扩展也可在 GitHub 在以下 URL:

https://github.com/gildas-lormeau/JSONView-for-Chrome

如果您使用Microsoft Edge,您可以直接在浏览器中查看原始 JSON 数据。 一旦您的浏览器准备好了,您就可以从 Visual Studio 的顶部工具栏中选择您想要的浏览器。 点击Debug按钮旁边的小三角形图标,然后选择浏览器,如下图所示:

<graphics/image_04_017.jpg>

在上面的截图中,您可以看到安装了多种浏览器,包括 Firefox、谷歌 Chrome、Internet Explorer 和 Edge。 要选择一个不同的浏览器,只需点击浏览与… ,在菜单中选择一个不同的。

现在,点击Debug按钮(也就是绿色的play按钮)来查看 Web API 项目在您的 Web 浏览器中的运行情况,如下面的截图所示。 如果你没有设置一个 web 应用,你将无法从根 URL 浏览网站:

<graphics/image_04_018.jpg>

如果你看到这个错误,不要担心,你可以更新 URL 来包含 API 控制器的路径; 例如,见http://localhost:12345/api/Patient

请注意,您的端口号可能有所不同。 现在,你应该能够看到 API 控制器吐出的视图列表,如下面的截图所示:

<graphics/image_04_019.jpg>

添加路由来处理预期的 URL 路径

在经典 ASP 时代,应用 URL 路径通常反映物理文件路径。 这在 ASP 中继续.NET web 表单,尽管引入了自定义 URL 路由的概念。 ASP.NET MVC,路由被设计为迎合功能而不是物理路径。

ASP.NET Web API 延续了这一较新的传统,它能够在代码中设置自定义路由。 您可以在启动代码中使用流畅的配置或使用方括号包围的声明性属性为应用创建路由。

了解路线

为了理解使用路由的目的,让我们关注一下路由在应用中的特性和好处。 这适用于 ASP。 asp.net MVC 和 asp.net.NET Web API:

  • 通过定义路由,您可以为 URL 访问引入可预测的模式
  • 这使您能够更好地控制如何将 url 映射到您的控制器
  • 人类可读的路径也是 seo 友好的,这对于搜索引擎优化非常好
  • 当涉及到揭示系统中的底层 web 技术和物理文件名时,它提供了某种程度的隐晦

设置路由

让我们从这个简单的类级属性开始,它为你的 API 控制器指定一个路由,如下所示:

[Route("api/[controller]")] 
public class PatientController : Controller 
{ 
  // ... 
} 

在这里,我们可以剖析属性(在方括号中看到,用于影响它下面的类)和它的参数,以了解发生了什么:

  • Route属性表明我们将为这个控制器定义一个路由。
  • 在后面的括号中,路由路径用双引号定义。
  • 该路径的第一部分是字符串字面值api/,它声明到 API 方法调用的路径将以术语api开始,后跟一个正斜杠。
  • 路径的其余部分是方括号中的单词controller,它指的是控制器名称。 根据约定,控制器名是控制器类名的一部分,该类名位于术语Controller之前。 对于类PatientController,控制器名称就是单词Patient
  • 这意味着该控制器的所有 API 方法都可以使用以下语法访问,其中MyApplicationServer应该替换为您自己的服务器或域名:http://MyApplicationServer/api/Patient

对于方法调用,可以定义带参数或不带参数的路由。 下面的例子演示了这两种类型的路由定义:

[HttpGet] 
public IEnumerable<string> Get() 
{ 
    return new string[] { "value1", "value2" }; 
} 

在本例中,Get()方法执行与 HTTP 动词HttpGet相关的操作,该动作声明在该方法的正上方的属性中。 这标识了在不带任何参数的情况下通过浏览器访问控制器的默认方法,这意味着可以使用以下语法访问此 API 方法:

http://MyApplicationServer/api/Patient 

要包含参数,我们可以使用以下语法:

[HttpGet("{id}")] 
public string Get(int id) 
{ 
    return "value"; 
} 

这里,HttpGet属性与"{id}"参数耦合,用双引号括起来的花括号。 方法的覆盖版本还包括一个名为id的整数值,以与期望的参数相对应。

如果不指定任何参数,则id的值等于default(int),即为零。 它可以在不带任何参数的情况下调用,语法如下:

http://MyApplicationServer/api/Patient/Get 

为了传递参数,你可以在控制器名称后添加任何整数值,语法如下:

http://MyApplicationServer/api/Patient/1 

这将把数字1分配给整数变量id

测试路线

要测试上述路由,只需从 Visual Studio 运行应用并访问不带参数的指定 url。

<graphics/image_04_020.jpg>

上图显示了进入以下路径的结果:

http://MyApplicationServer/api/Patient/1 

从客户端应用中使用 Web API

如果 Web API 公开公共端点,但没有客户端应用来使用它,那么它真的存在吗? 不需要太过理性,让我们来讨论一下使用客户机应用的可能方法。

你可以做以下任何事情:

  • 使用外部工具使用 Web API
  • 使用移动应用使用 Web API
  • 使用 Web 客户端使用 Web API

使用外部工具进行测试

如果没有设置客户机应用,可以使用外部工具,如Fiddler。 Fiddler 是一个免费的工具,现在可以从 Telerik 获得,在http://www.telerik.com/download/fiddler,如下截图所示:

<graphics/image_04_021.jpg>

您可以使用 Fiddler 检查在您的机器上检索和提交的 url。 您还可以使用它来触发任何 URL,并更改请求类型(Get、Post 等)。

从移动应用中使用 Web API

因为本章主要是关于 ASP.NET Core Web API,我们不会详细讲移动应用开发。 但是,需要注意的是,Web API 可以为您的移动应用项目提供后端。

移动应用可能包括 Windows 移动应用,iOS 应用,Android 应用,以及任何你可以为今天的智能手机和平板电脑构建的现代应用。 您可以参考您所选择的特定平台的文档,以确定需要什么来调用 RESTful API。

从 Web 客户端使用 Web API

在这种情况下,web 客户端指的是任何能够调用 RESTful API 的 HTML/JavaScript 应用。 至少,您可以使用直接的 JavaScript 构建一个完整的客户端解决方案来执行必要的操作。 为了获得更好的体验,您可以使用 jQuery 和许多流行的 JavaScript 框架之一。

一个 web 客户端也可以是一个更大的 ASP 的一部分.NET MVC 应用或单页应用(SPA)。 只要您的应用输出 HTML 页面中包含的 JavaScript,您就可以构建一个与后端 Web API 一起工作的前端。

总结

在本章中,我们已经了解了 ASP 的基本结构.NET Web API 项目,并观察了在 asp.net 中 Web API 与 MVC 的统一。 净的核心。 我们还学习了如何使用 Web API 作为后端来为各种前端应用提供支持。

在下一章中,我们将学习更多关于使用 HTML5、JavaScript 和 CSS3 开发交互式前端 UI 的知识。 我们将关注使用 JavaScript 来使用 Web API,同时介绍客户端工具,如 Bower、Grunt 和 Gulp。**

五、使用 JavaScript 与 Web API 交互

一个基于浏览器的 web 应用如果没有客户端代码来补充服务器端代码就不完整。 不管在 web 服务器上使用的技术和语言是什么,所有的 web 应用开发人员都应该学习如何在客户端使用 HTML 使用 JavaScript。

在本章中,我们将从构建一个充满 JavaScript 代码的 HTML 页面开始,以开发一个交互式用户界面。 我们将涵盖以下议题:

  • 使用 ASP.NET Web API 使用 JavaScript
  • JavaScript 框架
  • 客户端工具如BowerGruntGulp

使用 JavaScript 与 Web API 交互

有很多 JavaScript 框架正在争夺世界范围内的 web 开发人员的喜爱,其中一些已经流行起来。 在接下来的几节中,我们将学习AngularJSKnockoutJS。 但是首先,让我们关注使用一些基本的 JavaScript 来从 Web API 中读写数据。

本节的示例将使用以下文件:

  • HTML 文件与客户端 JavaScript 使用 Web API
  • 服务器端控制器类
  • 服务器端模型类

下面的截图显示了前面三个我们需要的文件:

<graphics/image_05_001.jpg>

我们将在本章的例子中处理这些文件:

  • 静态 HTML 文件位于 web 应用的wwwroot位置
  • 控制器位于Controllers文件夹中(按惯例)
  • 患者模型在Models文件夹中(按惯例)

为了直观地看到该应用的外观,请看下面的患者记录应用的截图:

<graphics/image_05_002.jpg>

准备服务器端代码

Models文件夹中创建一个新的类文件,并使用以下代码将其命名为Patient.cs:

public class Patient 
{ 
    public int Id { get; set; } 
    public string LastName { get; set; } 
    public string FirstName { get; set; } 
    public string SocialSecurityNumber { get; set; } 
} 

前面的代码为我们提供了适当数量的控制器和模型代码,以便开始使用客户端 JavaScript。

下面的 API 控制器至少有两个控制器方法来返回患者列表,或者在给定患者 ID 时只返回一个患者。 这个控制器应该有一个 using 语句来引用模型名称空间。

它以类级别的[Route]属性开始,表示如何从 web 浏览器的 GET 请求或通过浏览器中的 JavaScript 代码访问 API 控制器,如下所示:

[Route("api/[controller]")] 
public class PatientController : Controller 

在类本身内部,有一个类级实例变量,它包含一个数据结构,用于定义带有几个示例值的患者数组,如下面的代码所示。 在现实世界的应用中,这些数据通常来自一个数据库:

    Patient[] patients = new Patient[] 
    { 
        new Patient 
        { 
            Id = 1, 
            FirstName = "John", 
            LastName = "Smith", 
            SocialSecurityNumber = "123550001" 
        }, 
        new Patient 
        { 
            Id = 2, 
            FirstName = "Jane", 
            LastName = "Doe", 
            SocialSecurityNumber = "123550002" 
        }, 
        new Patient 
        { 
            Id = 3, 
            FirstName = "Lisa", 
            LastName = "Smith", 
            SocialSecurityNumber = "123550003" 
        } 
    }; 

接下来,我们有一个简单的Get()方法来返回一个可枚举的患者对象列表:

    // GET: api/patient 
    [HttpGet] 
    public IEnumerable<Patient> Get() 
    { 
        return patients; 
    } 

最后,我们有一个简单的Get(id)方法,当提供一个数字 ID 值来执行查找时,返回一个特定的患者:

    // GET api/patient/5 
    [HttpGet("{id}")] 
    public Patient Get(int id) 
    { 
        var patient = patients.FirstOrDefault((p) => p.Id == id); 
        if (patient == null) 
        { 
            return null; 
        } 
        return patient; 
    } 
} 

客户端 JavaScript

以下 HTML/JavaScript 代码可以包含在示例 HTML 文件中,以获取和显示患者记录。 它以一个典型的 HTML 开头:

<!DOCTYPE html> 
<html> 
<head> 
    <title>Patient Records App</title> 
</head> 

正文包含一个头部和一个<div>来显示数据:

<body> 

<div> 
    <h2>Patient Records</h2> 
    <ul id="patients"></ul> 
</div> 
<div> 
    <h2>Find Patient By ID</h2> 
    <input type="text" id="patientId" size="5" /> 
    <input type="button" value="Search" onclick="find();" /> 
    <p id="patient" /> 
</div> 

请注意以下几点:

  • 定义了一个 ID 为patients的空列表,用于在页面首次加载时显示患者记录列表
  • 搜索文本框的 ID 定义为patientId,允许用户通过 ID 进行搜索
  • Search按钮有一个onclick事件,该事件调用find()方法
  • 使用 IDpatient定义一个空段落,以显示调用find()方法的结果

接下来是对 jQuery 的引用,它可以是一个特定的(或最新的)版本,根据需要:

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script> 

然后,我们开始主要的<script>来定义函数来处理 API 调用:

<script> 

在脚本的开始,让我们定义一个变量来保存 API 调用的 URI 路径:

var uri = 'api/Patient'; 

接下来,让我们确保在页面加载后立即填充患者列表:

$(document).ready(function () { 
    $.getJSON(uri) 
        .done(function (data) { 
            $.each(data, function (key, patient) { 
                $('<li>', { 
                    text: formatPatientInfo(patient) 
                }).appendTo($('#patients')); 
            }); 
        }); 
}); 

前面的代码引用了一个名为formatPatientInfo()的函数,用于格式化 API 调用返回的患者信息。 该方法定义如下:

function formatPatientInfo(patient) { 
    if (patient && patient.lastName) 
        return patient.lastName + 
            ', ' + patient.firstName + 
            ': ' + patient.socialSecurityNumber; 
    else 
        return 'No patient information found.'; 
} 

为了启用搜索功能,定义一个find()方法如下:

function find() { 
    var id = $('#patientId').val(); 
    $.getJSON(uri + '/' + id) 
        .done(function (data) { 
            $('#patient').text(formatPatientInfo(data)); 
        }) 
        .fail(function (jqXHR, textStatus, err) { 
            $('#patient').text('Error: ' + err); 
        }); 
} 

这里定义了一个id变量,以从提供给最终用户的搜索框中获取数字 ID 值。 然后,这个 ID 被附加到前面定义的 URI 的末尾,形成一个用于调用getJSON()的 URL。

一旦 API 调用被触发,JavaScript 分别用.done.fail块处理成功和失败的调用。 .done块更新。

此时,我们可以关闭<script><body><html>标签:

</script> 
</body> 
</html> 

要验证您可以在您的 web 应用中显示静态文件,执行以下步骤:

  1. 验证Main()包含。 Program.cs中的UseContentRoot(Directory.GetCurrentDirectory())
  2. 添加对Microsoft.AspNetCore.StaticFiles(1.0.0)的引用。
  3. app.UseStaticFiles()加到Startup.cs中。

以下截图显示了用户搜索 ID 为1的患者时显示的结果:

<graphics/image_05_003.jpg>

JavaScript 框架

当您开始向代码中添加越来越多的 JavaScript 时,您的 web 应用将变得笨拙且难以维护。 要利用提供的 JavaScript 框架,您可以从许多 JavaScript 框架中进行选择。

以下是四种流行的框架:

在本章中,我们将专注于 AngularJS 和 KnockoutJS。

使用 AngularJS 的单页应用

官方的 ASP.NET 文档中提到,AngularJS 是构建 spa 风格的 ASP 的一个选项。 网络应用。 本章中的例子来自微软的文档:http://docs.asp.net/en/latest/client-side/angular.html

开始学习 AngularJS

AngularJS 是一个开源的 JavaScript 框架,由谷歌官方维护。 在撰写本文时,最新的稳定版本是 1.5 版。 到 2016 年 7 月为止,2.0 版本正在经历几个发布候选(RC)阶段。

AngularJS 使用了 jQuery 的一个子集jqLite,它允许它在多个浏览器上操作 HTML 页面的 DOM。 如果你想在 AngularJS 应用中使用 jQuery,你必须确保 jQuery 是在angular.js文件之前加载的。

在 Visual Studio 2015 中将 AngularJS 设置到你的 web 应用中最简单的方法是在一个新的 web 应用中更新你的bower.json文件。 启动 Visual Studio 2015,点击File|New|Project,然后使用新的ASP 创建一个新的Web 应用**.NET 模板**(不是空的)。

这将自动为您创建一个bower.json配置文件。 您可能必须单击解决方案资源管理器中的Show All Files图标才能查看bower.json文件。 只需编辑此 JSON 文件,在"dependencies"下添加"angular""angular-route"两个条目。 使用智能感知来帮助你决定使用哪个版本号,如下截图所示:

<graphics/image_05_004.jpg>

鲍尔。 json 文件

angular-route模块允许您的 web 应用使用路由和深度链接服务,以及指令。 这些术语(以及更多)将在下一节中解释。

几乎在添加这两个条目之后,必需的 JavaScript 文件将被添加到/Dependencies/Bower/下的Bower文件夹中,如下截图所示。 您可以配置 Grunt 或 Gulp 始终将必要的文件复制到wwwrootweb 根目录中的lib子文件夹中。

<graphics/image_05_005.jpg>

Angular(1.5.8)和 Angular 路由(1.5.8)

下面的截图显示了你的lib文件夹在放入必要的模块后应该是什么样子:

<graphics/image_05_006.jpg>

在本章的最后一节中,我们将学习更多关于使用 Bower 管理客户端代码的包的知识。

AngularJS 的语法和特性

AngularJS 可以通过几个例子来解释它的语法和特性。 HTML 文件中的 AngularJS 语法可以通过以下方法轻松识别:

  • 出现在 HTML 标记中的指令,例如ng-appng-init
  • 双花括号中的表达式,例如{{1+2}}
  • 数据绑定ng-bind,如<span ng-bind="ssn"></span>
  • 枚举数据的重复器,例如<li ng-repeat="patient in patients">
  • 用于处理用户输入的事件处理程序,例如<button ng-click="handleClick()">
  • 上述所有内容都可以包含在被称为模板的 HTML 文件中。

在 JavaScript 代码文件中,你可能会认识到以下一些语法:

  • angular.module()定义的 App 模块
  • .factory()定义的模型工厂
  • .service()定义的服务
  • .controller()定义的控制器

这并不是一个详尽的列表,本章也不打算取代 AngularJS 文档或教程。 要了解更多关于 AngularJS 的信息,请阅读官方文档https://docs.angularjs.org

用 AngularJS 构建一个 web 应用

一旦你在你的项目中建立了依赖关系,在你的 HTML 代码中添加一个指向 AngularJS 的脚本引用。 可以通过以下方式添加:

  • 在您的_Layout.cshtml文件中/Views/Shared
  • 在静态 HTML 页面中,刚好在关闭</body>标记之前

布局文件对于DevelopmentStaging/Production有不同的部分。 虽然您可以使用本地参考进行开发,但您应该使用来自内容交付网络(CDN)的共享 URL 进行登台和生产,如下所示:

<environment names="Development"> 
    <script src="~/lib/jquery/dist/jquery.js"></script> 
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script> 
</environment> 

对于登台和生产,AngularJS 常用的 CDN 服务器包括谷歌的 CDN 在 ajax.googleapis.com 或微软的 AJAX CDN 在 ajax.aspnetcdn.com。

静态 HTML 文件要简单得多,因为它只引用本地文件。 您还可以使用智能感知来键入angular.js文件的路径,因为当您键入时,Visual Studio 将在您的系统上定位该文件。 下面的代码做到了这一点:

    <script src="../lib/angular/angular.js"></script> 
</body> 
</html> 

以下静态 HTML 文件可以保存到项目的wwwrootweb 文件夹中,而其他 JavaScript 文件也可以保存在此:

<graphics/image_05_007.jpg>

下面的代码显示了一个名为ng-hello.html的简单 HTML 文件的内容:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>Hello, Angular!</title> 
</head> 
<body ng-app> 
    <h1>Hello, Angular!</h1> 

    Calculate (2016 - 1990) = {{2016-1990}} 
    <script src="../lib/angular/angular.js"></script> 
</body> 
</html> 

以下截图是ng-hello.html的输出:

<graphics/image_05_008.jpg>

注意,表达式{{2016-1990}}实际上是作为算术操作计算的,结果(26)显示在浏览器中。

下面的代码显示了在示例文件ng-binding.html中运行的数据绑定:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>Data Binding in Angular</title> 
</head> 
<body ng-app> 
    <h1>Data Binding in Angular</h1> 
    <h2>Patient Details</h2> 

    <ul ng-init="lastName='Smith'; firstName='John';socialSecurityNumber='123550001'"> 
        <li>Name: {{lastName}}, {{firstName}}</li> 
        <li>SSN: <span ng-bind="socialSecurityNumber"></span></li> 
    </ul> 

    <script src="../lib/angular/angular.js"></script> 
</body> 
</html> 

以下截图是ng-binding.html的输出:

<graphics/image_05_009.jpg>

请注意以下几点:

  • <body>标签中的ng-app指令指明了 Angular 应用的根元素
  • <ul>标记中的ng-init指令以<ul>块的范围初始化表达式
  • 第一个<li>元素中的双花括号计算在<ul>中初始化的变量。
  • 第二个<li>元素中的ng-bind指令是另一种绑定变量的方式
  • 两种数据绑定方式都是有效的

下面的代码显示了示例文件ng-repeater.html中的中继器:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>Angular Repeaters</title> 
</head> 
<body ng-app> 
    <h1>Angular Repeaters</h1> 

    <h2>Patient Records</h2> 
    <div ng-init="patients=['Smith, John','Doe, Jane', 'Smith, Lisa']"> 
        <ul> 
            <li ng-repeat="patient in patients"> 
                {{patient}} 
            </li> 
        </ul> 
    </div> 

    <script src="../lib/angular/angular.js"></script> 
</body> 
</html> 

以下截图是ng-repeater.html的输出:

<graphics/image_05_010.jpg>

在此,请注意以下几点:

  • ng-init指令初始化一个简单的患者名称数组,每个名称存储在一个字符串中
  • ng-repeat指令枚举数组中的每个患者
  • 双花括号出现在<li>元素中,并在 DOM 中生成的最终 HTML 中重复

下面的代码展示了一个使用我们在前一章中创建的 Web API 控制器的基本示例,在示例文件ng-rest.html中:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>RESTful Endpoints from Angular</title> 
</head> 
<body ng-app="patientRecordsApp"> 
    <h1>RESTful Endpoints from Angular</h1> 

    <div ng-controller="patientController"> 
        <ul> 
            <li ng-repeat="patient in patients"> 
                {{patient.lastName}}, {{patient.firstName}} 
            </li> 
        </ul> 
    </div> 

    <script src="../lib/angular/angular.js"></script> 
    <script src="../js/ng-rest.js"></script> 
</body> 
</html> 

它在客户端使用模型视图控制器模式,让控制器更新模型数据,然后在 HTML 中显示这些数据。 在下面的代码中,你会注意到一个名为ng-rest.js的 JavaScript 文件的引用:

(function () { 
    'use strict'; 
    var prApp = angular.module('patientRecordsApp', []); 
})(); 

(function () { 
    'use strict'; 

    var pService = 'patientFactory'; 

    angular.module('patientRecordsApp').factory(pService, 
        ['$http', patientFactory]); 

    function patientFactory($http) { 

        function getPatientsFromApi() 
        { 
            // NOTE: the port number should be changed as necessary  
            return $http.get('http://localhost:50915/api/Patient'); 
        } 

        var patientService = { 
            getPatientsFromApi: getPatientsFromApi 
        }; 
        return patientService; 
    } 
})(); 

(function () { 
    'use strict'; 

    var pController = 'patientController'; 

    angular.module('patientRecordsApp').controller(pController, 
        ['$scope', 'patientFactory', patientController]); 

    function patientController($scope, patientFactory) { 
        $scope.patients = []; 

        patientFactory.getPatientsFromApi().success(function (patientData) { 
            $scope.patients = patientData; 
            console.log("Data obtained successfully."); 
        }).error(function (error) { 
            console.log("An error has occured."); 
        }); 
    } 
})(); 

在前面的代码中,getPatientsFromApi()方法负责调用服务器端代码中的 API 方法,在 web 浏览器中显示如下结果:

<graphics/image_05_011.jpg>

要让之前的 Angular 样例正常工作,首先运行之前的 Web API 项目,并在执行 API 调用之前引用 API URL 的特定端口号。 如果你愿意,你也可以在你的 Angular 项目中添加一个新的服务器端 API 控制器。

模型-视图- viewmodel (MVVM)与 KnockoutJS

官方的 ASP.NET 文档提到 KnockoutJS 是构建模型-视图- viewmodel(MVVM)web 应用的一个选项; 见http://docs.asp.net/en/latest/client-side/knockout.html

了解 KnockoutJS

KnockoutJS 是一个流行的 JavaScript 框架,您可以单独使用它,也可以与 jQuery 和其他 JavaScript 库一起使用。 它在客户端使用 MVVM 模式,促进 HTML 元素和 JavaScript 变量之间的数据绑定。

与 AngularJS 类似,在 Visual Studio 2015 中将 KnockoutJS 设置到你的 web 应用中最简单的方法就是在一个新的 web 应用中更新你的bower.json文件。 再次启动 Visual Studio 2015 中,点击文件||项目,,然后创建一个新的 Web 应用使用新的【显示】ASP.NET 模板**(不是空的)。**

与前面一样,这将自动创建一个可以编辑的bower.json配置文件。 在"dependencies"下面为knockout"添加一个条目。 你可以使用智能感知来帮助你决定使用哪个版本号。 再次,您可能必须单击解决方案资源管理器中的显示所有文件以查看bower文件。 bower文件如下截图所示:

<graphics/image_05_012.jpg>

鲍尔。 json 文件"Knockout": “3.4.0”

几乎在你添加条目之后,必要的 JavaScript 依赖会被添加到你的Bower文件夹下的/Dependencies/Bower/,如下截图所示:

<graphics/image_05_013.jpg>

击倒(3.4.0)

下面的截图显示了 Knockout 模块放入你的lib文件夹后的样子:

<graphics/image_05_014.jpg>

KnockoutJS 语法和特性

KnockoutJS 语法可以通过以下方式理解:

  • 在 HTML 标记中使用data-bind属性设置数据绑定
  • 使用.applyBindings()将绑定与数据模型关联起来
  • 对对象使用observable()自动更新
  • 对集合使用observableArray()自动更新
  • 为一个或多个可观察对象使用computed()的自定义绑定

要了解 KnockoutJS 的更多信息,请阅读官方文档http://knockoutjs.com/documentation/introduction.html

用 KnockoutJS 构建一个 web 应用

一旦在项目中设置了依赖项,就可以在 HTML 代码中添加对 KnockoutJS 的脚本引用。

下面的代码展示了将<span>元素绑定到示例文件ko-hello.html中的简单数据值的基本示例:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>Hello, Knockout!</title> 
    <script type="text/javascript" src="../lib/knockout/dist/knockout.js"></script> 
</head> 
<body> 
    <h1>Hello, Knockout!</h1> 

    <h2>Patient Details</h2> 

    Name: <span data-bind="text: patientName"></span> 

    <script type="text/javascript"> 
        var patientViewModel = { 
            patientName: 'John Smith' 
        }; 
        ko.applyBindings(patientViewModel); 
    </script> 

</body> 
</html> 

以下截图显示了ko-hello.html的输出:

<graphics/image_05_015.jpg>

你会注意到以下几点:

  • 一个<script>标签标识了 KnockoutJS 的位置
  • <span>标记使用data-bind属性作为文本值来显示patientName
  • 视图模型定义为一个属性patientName
  • 通过传递数据模型来调用ko.applyBindings()来建立连接

为了直接进入一个 Web API 示例,下面的代码调用一个 Web API 方法来获取示例文件ko-rest.html中的患者记录列表:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>Web API from KnockoutJS</title> 
    <script type="text/javascript" src="../lib/jquery/dist/jquery.js"></script> 
    <script type="text/javascript" src="../lib/knockout/dist/knockout.js"></script> 
</head> 
<body> 
    <h1>Web API from KnockoutJS</h1> 

    <h2>Patient Details</h2> 

    <ul data-bind="foreach: Patients"> 
        <li> 
            <span data-bind="text: lastName"></span>,  
            <span data-bind="text: firstName"></span> 
        </li> 
    </ul> 

    <script type="text/javascript"> 
    var patientViewModel = function () { 
        var self = this; 
        self.Patients = ko.observableArray(); 
        LoadPatientData(); 

        // NOTE: the port number below should be changed as necessary  
        function LoadPatientData() { 
            $.ajax({ 
                type: "GET", 
                url: "http://localhost:50915/api/Patient", 
                contentType: "application/json; charset=utf-8", 
                dataType: "json", 
                success: function (data) { 
                    self.Patients(data);  
                }, 
                error: function (error) { 
                    console.log("An error has occurred."); 
                } 
            }); 
        } 
    }; 
    ko.applyBindings(new patientViewModel()); 
    </script> 

</body> 
</html> 

以下截图显示了ko-rest.html的输出:

<graphics/image_05_016.jpg>

在前面的例子中,你会注意到以下几点:

  • 一个<script>标记标识 jQuery 的位置
  • 第二个<script>标签标识了 KnockoutJS 的位置
  • <ul>标签使用data-bind属性来枚举患者列表
  • 每个<li>包含<span>标签与lastNamefirstName绑定
  • 一个基本的ViewModel被定义为容纳一个observableArray()患者
  • 一个名为LoadPatientData的函数调用 Web API
  • 最后,使用ViewModel调用ko.ApplyBindings()进行绑定

同样,如果是在不同的项目中,您必须确保 Web API 已经启动并运行。

使用 Bower、Grunt 和 Gulp 的任务运行器、捆绑和缩小

通过 Visual Studio 2015,微软引入了与客户端包管理器和任务运行器更紧密的集成。 为了充分利用这些工具,最好了解它们做什么以及何时使用它们。

为什么我们需要任务自动化?

你可以在没有智能感知的基本文本编辑器中逐行编写代码,但你很快就会渴望 Visual Studio 或富 IDE 来完成更多的工作。 这类似于手动执行某些任务,当您可以使用自动化工具使您的生活更轻松时。

使用 Bower 作为包管理器

要处理客户端依赖关系,您需要使用与开发环境配合良好的包管理器。 Bower 就是这样一个工具。

您将不再使用NuGet来安装诸如 jQuery 这样的客户端包,而是使用 Bower 来获取 JavaScript 库和 CSS 框架。 不必等待 NuGet 上出现最新版本的软件包,您可以使用 Bower 获得这些软件包,世界各地的开发人员已经在使用它。

如果您使用 starter 模板创建一个新的 web 项目,那么您将已经设置了一个 Bower 配置文件。 要从头开始设置它,创建一个新的空 web 项目,并为其创建一个新的配置文件,并遵循以下步骤:

  1. 在 Visual Studio 2015 中,点击File|New|Project
  2. 选择ASP.NET Core Web Application,并输入项目名称和位置。
  3. 为 ASP 选择模板。 净的核心。
  4. 右键单击 web 项目,然后点击添加|新项目
  5. 在客户端类别下,添加新的 Bower 配置文件,通常命名为bower.json

**在bower.json中,添加一个新的 bootstrap 依赖,如下所示:

{ 
  "name": "asp.net", 
  "private": true, 
  "dependencies": { 
    "bootstrap": "3.3.7" 
  } 
} 

使用智能感知来决定你想使用哪个版本的引导。 几乎立刻,wwwroot内的lib子文件夹就会被填充上引导(你添加的依赖项)和jquery(bootstrap 所依赖的)所需的文件,如下截图所示:

<graphics/image_05_017.jpg>

该位置是基于.bowerrc文件中的条目配置的,该文件位于bower.json旁边,但通常隐藏在解决方案资源管理器中。 以下代码来自.bowerrc:

{ 
    "directory": "wwwroot/lib" 
} 

有关使用 Bower 作为 ASP 的客户端包管理器的更多信息.NET Core 项目,查看官方文档http://docs.asp.net/en/latest/client-side/bower.html

使用 Gulp 和 Grunt 作为任务运行器

要在你的项目中设置 Gulp 和 Grunt,在项目级别添加一个新项目,类型为NPM 配置文件,名称为package.json。 然后,更新devDependencies部分,包括以下对 Gulp 和 Grunt 的引用:

{ 
  "version": "1.0.0", 
  "name": "asp.net", 
  "private": true, 
  "devDependencies": { 
    "gulp": "3.9.1", 
    "gulp-less": "3.1.0", 
    "grunt": "1.0.1", 
    "grunt-contrib-clean": "1.0.0" 
  } 
} 

在解决方案资源管理器中,验证这些依赖项现在在依赖项内的NPM文件夹中可见。 然后,添加一个名为styles.lessLESS文件到项目根目录的less子文件夹中,使用下面的 LESS 代码:

@light-gray: #C0C0C0; 
@darker-gray: @light-gray - #222; 

#banner { 
  color: @darker-gray; 
} 

这段 LESS 代码将自动为 ID 值为banner的 HTML 元素生成较深的灰色阴影,例如<div id="banner">

向项目中添加两个新项目,类型为Gulp 配置文件Grunt 配置文件,通常分别命名为gulpfile.jsgruntfile.js

将以下代码添加到gulpfile.js中,以监视 LESS 文件并在发生更改时编译 CSS 输出。 第一行中的指令还指示 Visual Studio 基于特定条件运行每个任务,比如在构建之后或在项目打开时:

/// <binding AfterBuild='stylemaker' ProjectOpened='lesswatcher' /> 
var gulp = require('gulp'); 
var gulpless = require('gulp-less') 

gulp.task('stylemaker', function () { 
    gulp.src("./less/styles.less") 
        .pipe(gulpless({ compress: true })) 
        .pipe(gulp.dest("./wwwroot/css")); 
}); 

gulp.task('lesswatcher', function () { 
    gulp.watch("./less/*.less", ["stylemaker"]); 
}); 

接下来,将以下代码添加到gruntfile.js中,以确保 CSS 输出文件夹被清理:

module.exports = function (grunt) { 
    grunt.initConfig({ 
        clean: ["wwwroot/css/*"], 
    }); 
    grunt.loadNpmTasks("grunt-contrib-clean"); 
}; 

可以通过任务运行器窗口运行上述任务,也可以通过配置绑定使任务根据特定条件运行。 如果任务运行程序管理器窗口不可见,在 Visual Studio 顶部菜单中单击View|Other Windows|任务运行程序管理器任务运行器管理器窗口如下截图:

<graphics/image_05_018.jpg>

有关使用 Grunt 和 Gulp 作为 ASP 的任务运行器的更多信息.NET Core 项目,查看以下网址的官方文档:

总结

在本章中,你学习了如何在 JavaScript 中使用 Web API,之后你学习了 AngularJS 和 KnockoutJS 的基础知识。 您还学习了客户端工具,这些工具在构建 ASP 时帮助自动化一些常见任务.NET web 应用在 Visual Studio 2015。

在下一章中,您将学习如何构建数据库驱动的 web 应用,而不需要编写 SQL 代码。 相反,您将使用Entity Framework,这是一个对象-关系映射器,允许您编写代码来表示数据库实体。**

六、在代码中使用实体框架与数据库交互

第三章理解 MVC中,我们在构建功能性 ASP 的同时提到了实体框架(EF).NET Core MVC web 应用。 在本章中,我们将深入了解 EF Core 1.0,并介绍在开发过程中你需要了解的关于 EF Core 的知识,也就是 EF7。

值得注意的是,EF Core 可以与不止 ASP 一起使用.NET Core 和关系数据库。 事实上,它也被设计用于与环球 Windows 平台(UWP)应用在 Windows 上 10 和 Windows 桌面应用(Windows Presentation Foundation (WPF)或【显示】WinForms)。 除了 SQL Server, EF Core 还可以与Azure Table Storage**,PostgreSQLSQLite,甚至NoSQL数据库一起使用。******

****为了本书的目的,我们将主要关注 ASP.NET Core、SQL Server 和新的内存提供程序。

.NET 中的对象关系映射

如果您以前使用过 EF 或任何对象关系映射器(ORM),那么您可以略读本节并继续下一节。 但是,如果您是 ORM 框架的新手,那么本节是为您准备的。

像 EF 这样的 ORM 使您可以很容易地在应用代码中与数据库进行交互。 下面的截图说明了 ORM:

<graphics/image_06_001.jpg>

为什么使用 ORM?

在没有任何 ORM 的情况下构建一个功能齐全的 web 应用是完全可行的。 你可以直接使用 ADO.NET 或原始 SQL 从应用代码与数据库对话。 您可以编写 SQL 代码来创建数据库对象和关系。 您可以通过大量使用存储过程和函数来将所有数据库逻辑保存在数据库中,或者您可以使用像 EF 这样的 ORM 并利用Code First方法。

虽然数据库管理员可能会嘲笑 ORM 的使用,但开发人员应该有信心,他们将获得更多的权力和控制如何创建、操纵和维护数据库实体。 以下是你可以考虑的利弊清单。

使用 ORM 的优点:

  • 公共代码库:您可以在代码中定义所有实体,而不是在应用代码库之外断开数据库创建代码
  • 编译时的好处:如果你在模型代码中犯了某些错误,编译器会捕获它们
  • 更容易的更新:如果你需要更新/重命名模型中的任何东西,你的 IDE 会让它变得轻而易举
  • 无忧约束:您可以使用属性和流畅的代码轻松设置键、关系和其他约束
  • 可管理的维护:在迁移的帮助下,您和您的团队可以根据需要升级/降级您的数据库,并跟踪修订。

使用 ORM 的缺点:

  • 学习曲线:如果你以前没有使用过 ORM,你不可能一天之内就把它添加到现有的应用中。 在更新的项目中开始使用它,在更新现有项目时花点时间。
  • 复杂查询:如果你或你的团队已经精通 SQL 查询,你可能有困难重建复杂查询的结果使用综合语言查询(LINQ)语法。 随着时间的推移,您可能会变得更容易,或者您可能会认为 orm 不适合特定的应用。
  • 性能(有争议):当第一次引入 orm 时,您可能已经考虑了在应用代码和数据库之间添加另一层对性能的影响。 但对于现代 ORM 框架(如 EF Core),性能的改进应该使其值得付出努力,而无需太过担心。

现在我们已经了解了优点和缺点,让我们关注一下为什么您会选择 EF 作为您的 web 应用的 ORM。

为什么是实体框架?

如果你以前使用过 orm,你可能使用过NHibernate或更早版本的 EF。 您可能已经在 Java 应用中使用了Hibernate。 不管你的背景如何,有很多理由说明 EF 对你的 ASP 来说是一个不错的选择.NET Core 应用。

首先,新的 EF 与新的 ASP.NET 不像以前的其他版本。 早期版本的 EF 运行时和工具是与。net 框架一起发布的,但是最近的版本将运行时分离出来,从而通过 NuGet 实现带外发布。 运行时的最新版本可以通过 NuGet 获得,而主要版本与 Visual Studio 版本同步。

实体框架的演变

随着时间的推移,EF 已经有了很大的进步。 代码优先方法和 EF 迁移的引入让许多开发人员注意到这一点。 与此同时,还有很多开发人员还没有与 EF 合作过。

多年来,EF 团队一直在不断收集开发人员对其产品的反馈。 因此,该团队已经将一个成熟的产品整合在一起,并且随着时间的推移,这个产品会变得越来越好。

如果您有兴趣提供反馈或查看来自其他开发人员的输入,请访问https://data.uservoice.com

出现的一些新特性包括批处理更新、阴影属性、内存提供程序以及处理断开连接数据的改进方法。 我们将在本章中更详细地讨论新特性,通过一个示例项目来说明这些特性是如何结合在一起的。

5 .ef .NET Framework vs . EF Core 1.0

如果你一直使用 EF 6 到现在,你应该花时间了解 EF Core 有什么变化。 EF 的基本概念和用法应该是大家熟悉的,但是这里有一些新的添加(和一些删除),这将影响你学习 EF Core 的学习曲线。

如果您一直在进行代码优先开发,那么您应该已经熟悉了在应用代码中构建自己的模型。 如果您已经使用了 Migrations,那么您还应该熟悉如何通过触发迁移来生成/更新数据库。 但是,如果您已经习惯了可视化数据建模工具和 EDMX 文件,那么您可能需要忘掉一些东西。 EDMX 文件是实体数据模型文件,可以使用早期版本的 EF 可视化地表示数据模型。

EF Core 有什么不同

首先,值得注意的是,不再支持将 EDMX 文件作为创建数据模型的方法。 这并不意味着没有方法可视化地建模您的数据库,或者从数据库优先的方法开始。 相反,如果您愿意,您仍然可以从一个现有的数据库开始,并使用外部工具来生成您的模型类。

也就是说,我们将专注于 EF Core 的代码优先方法。 这很重要,因为它将帮助您更好地控制模型类,这将使代码合并更容易。

EF 以前的版本依赖于ObjectContext作为在代码中将数据库实体作为对象的一种方法。 即使在 EF 4.1 中使用了DbContext API,下面仍然继续依赖于原来的ObjectContext。 在 EF Core 中,ObjectContext将离开我们,但DbContext保留。 代表了一系列设计模式的组合,这些设计模式允许您从应用代码中轻松地使用数据库。

虽然 EF6 可以通过 NuGet 获得,但 EF Core 将其依赖管理提升到与 ASP 保持一致的另一个级别。 净的核心。 您可以选择只使用您需要的部分,包括针对 Core、Commands、Relational(包括迁移)和 SQL Server 的单独包。 如果您包含一个特定的包作为引用,Visual Studio 2015 将根据需要自动包含额外的依赖项。

EF Core 入门

如果你在 Visual Studio 2015 中使用标准的 Web 应用模板创建一个新的 Web 应用项目,你应该已经设置了 EF Core。 您可能还记得第 3 章、了解 MVC中的患者记录 web 应用,在其中我们建立了一个具有数据库连接的基本 web 项目。

如果您从一个空项目开始,您应该在您的project.json配置文件中键入 EF 引用。 在我的患者记录应用中,我有以下参考:

"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0" 

在“解决方案资源管理器”面板中,您可以展开每个引用,以识别自动作为依赖项拉入的相关引用,如下面的截图所示:

<graphics/image_06_002.jpg>

根据添加引用的时间,版本号可能有所不同。 虽然你可以在配置文件中输入任何当前或以前的版本,但你很可能会让 Visual Studio 的智能感知功能用弹出的工具提示建议来指导你。

Startup.cs文件中,应该在ConfigureServices()方法中调用AddEntityFrameworkStores(),然后调用添加特定的数据库提供程序和要使用的数据库上下文。 要使用 EF Core,首先要确保以下 using 语句出现在你的Startup.cs文件中:

using Microsoft.EntityFrameworkCore; 

在我的患者记录申请中,ConfigureServices()方法如下:

public void ConfigureServices(IServiceCollection services) 
{ 
    // Add framework services. 
    services.AddDbContext<ApplicationDbContext>(options => 
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

    services.AddIdentity<ApplicationUser, IdentityRole>() 
        .AddEntityFrameworkStores<ApplicationDbContext>() 
        .AddDefaultTokenProviders(); 

    // rest of method removed for brevity 
} 

前面的代码包含以下术语和方法调用:

  • Microsoft.EntityFrameworkCore:此命名空间提供对 EF Core 的访问
  • AddDbContext<>():这增加了一个db上下文,称为ApplicationDbContext
  • UseSqlServer():配置 SQL Server 数据库连接

数据库上下文位于其自己的类文件ApplicationDbContext.cs中,位于您的Data文件夹中。 在这里您将添加一个或多个DbSet条目来表示您的实体。

数据库连接字符串可以作为文本值存在于appsettings.json文件中,该文件位于项目位置的根目录中。 这个连接字符串还可以作为特定环境的环境变量存在,无论它是开发机器、内部服务器还是云环境。

设置好引用和配置文件之后,现在就可以在代码中使用 EF 了。

还有什么新鲜事吗?

在我们进入剩下的代码之前,让我们看看 EF Core 还有什么新的地方:

  • Migrations History:在 EF 的以前版本中,每次新的迁移(即数据库修订)都会在数据库中的一个特殊表中生成一个新条目。 EF Core 中仍然存在这样一个表,它被称为__EFMigrationsHistory,但是它被简化了,除了产品版本之外,只包含一个字母数字迁移 ID。
  • 快照:迁移历史表用于包含每次迁移的快照,但它已被移动到Data文件夹中的Migrations子文件夹(如ApplicationDbContextModelSnapshot.cs)中的代码文件中。 实际的文件名可能会根据数据库上下文的名称而有所不同。
  • 批量更新:EF Core 根据应用代码生成 SQL 语句来运行数据库命令。 在设置数据库上下文时,可以配置最大批处理大小。
  • 阴影属性:您可以使用阴影属性在数据库上下文中从OnModelCreating()方法中动态扩展您的模型。 这些更改将在您的数据库中进行,但不会影响实际的模型文件。
  • 内存提供程序:与其直接与实际的数据库交互,你可以选择使用内存提供程序。 这在设置和运行单元测试时也很有用。
  • 断开连接的数据:有一些改进的方法可以处理断开连接的数据,这应该可以让开发人员更容易地在断开连接的数据场景中添加和更新数据。

代码优先的数据库设计方法和关系

那么到底什么是代码优先的方法呢? 正如它听起来的那样。 可以在代码中将数据库对象建模为实体类。 要建立这些对象之间的关系,可以定义一个类以包含其他类作为成员变量。 如果您已经有一个现有的数据库,您可以在您的代码中创建一个实体模型来表示一些(或全部)数据库对象。

从我们从第 3 章了解 MVC的病人记录例子中,我们已经有了一个代表人的模型类。 在这一章中,我们将增加一个RobotDoctor班到我们的项目中,为一个未来医院与机器人医生建立一个电脑化系统。 然后我们将在代码中建立HumansRobotDoctors之间的关系,使每个机器人医生可以分配给数据库中的一个或多个人类患者。

更新模型

Models文件夹的示例项目从第 3 章,理解 MVC【显示】,让我们添加一个新的模型类来表示一个RobotDoctor``Human然后更新现有的类来添加字段识别每一个人类与机器人医生的关系。 我们还必须更新上下文文件ApplicationDbContext.cs,为每一组实体使用单独的DbSet

要添加RobotDoctor类,请执行以下步骤:

  1. 在“解决方案资源管理器”面板中,右键单击Models文件夹。

  2. 在上下文菜单中点击添加|新项目

  3. 将新类命名为RobotDoctor.cs

  4. RobotDoctor类添加以下代码:

    using System.ComponentModel.DataAnnotations; 
    
    namespace PatientRecords.Models 
    { 
        public class RobotDoctor 
        { 
            [Display(Name = "Robot Doctor ID")] 
            public int RobotDoctorId { get; set; } 
    
            [Display(Name = "Model Number")] 
            public int ModelNumber { get; set; } 
    
            [Display(Name = "Preferred Name")] 
            public string PreferredName { get; set; } 
        }  
    } 
    
    

将使用RobotDoctorId整数字段作为主键。 其余字段将分别存储和显示型号和首选名称。 Display属性将用作字段的友好文本标签。

要更新 Human 类,请遵循以下步骤:

  1. Models文件夹中打开Human.cs类文件。
  2. 在类的底部添加以下字段:
[Display(Name = "Robot Doctor")] 
public int RobotDoctorId { get; set; } 
public RobotDoctor RobotDoctor { get; set; } 

Human类中的RobotDoctorId整数字段将作为外键引用RobotDoctor类中相应的字段。 对象将允许将每个Human分配给特定的RobotDoctorDisplay属性将作为一个友好的文本标签用于字段。

要更新数据库上下文,请遵循以下步骤:

  1. Data文件夹中打开ApplicationDbContext.cs类文件。
  2. 在班级底部为RobotDoctors增加一个新的DbSet
  3. 通过将单词Human复数化为Humans来更新HumansDbSet,如下代码所示:

命名为RobotDoctorsDbSet将代表存储在数据库中的一组机器人医生。 命名为HumansDbSet将表示存储在数据库中的Humans集合。 虽然没有必要将其复数化,但这一微小的变化应该有助于阐明其目的。

更新控制器

当我们将ApplicationDbContext类中命名为HumanDbSet更新为Humans时,我们的HumanController仍然保留对旧名称的引用。 有两种方法可以解决这个问题:你可以在控制器文件中手动重命名HumanHumans的所有引用,或者你可以使用 Visual Studio 内置的重命名功能。

使用重命名功能,您可以点击DbSet名为Human在您的代码(重命名之前Human``Humans),然后用一套快速跟踪击键:Ctrl + R+【显示】。 这将允许您在引用新值的任何地方输入新值。 你将有机会通过选中相应的复选框来预览你的更改,如下图所示:

*<graphics/image_06_003.jpg>

在我们更新其余的控制器方法之前,请确保以下 using 语句位于HumanController类的顶部:

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

以下命名空间对于我们将在控制器中执行的任务是有用的:

  • 命名空间将允许我们使用异步方法。
  • Collections.Generic命名空间允许我们使用IEnumerable列表。
  • 命名空间System将允许我们使用String方法。

为了确保在Humans列表中包含每个HumanRobotDoctor数据,更新HumanController类的Index()方法以包含以下代码:

public async Task<IActionResult> Index() 
{ 
    var humans = _context.Humans.Include(h => h.RobotDoctor); 
    return View(humans); 
} 

在前面的代码中,对数据库上下文中名为HumansDbSet的调用和RobotDoctor数据由Include()方法拉出。 然后,该方法将人员集返回到相应的视图。 然后,视图负责遍历一个列表Humans以显示给用户。

为了确保我们在其Details页面中包含特定HumanRobotDoctor数据,更新Details()方法以包含以下代码:

public async Task<ActionResult> Details(int? id) 
{ 
    Human human = await _context.Humans 
        .Include(h => h.RobotDoctor) 
        .SingleOrDefaultAsync(h => h.ID == id); 
    if (human == null) 
    { 
        return NotFound(); 
    } 
    return View(human); 
} 

注意,命名为HumansDbSet后面是对Include()的调用,以确保RobotDoctor数据也包含在内。 在此过程中,我们还通过包括以下内容来利用异步方法调用:

  • 方法定义中的async关键字
  • Task<ActionResult>返回类型而不是ActionResult
  • SingleOrDefaultAsync()而不是Single()
  • 方法调用中的await关键字

接下来,让我们更新Create()方法的HttpGet版本,以便在显示一个创建新Humans的入口表单之前获得RobotDoctors列表。 由于HttpGet是控制器方法的默认谓词,因此该方法不需要一个属性来指示其HttpVerb。 用以下代码替换Create():

public IActionResult Create() 
{ 
    ViewBag.RobotDoctors = GetListOfRobotDoctors(); 
    return View(); 
} 

private IEnumerable<SelectListItem> GetListOfRobotDoctors(int selected = -1) 
{ 
    var tmp = _context.RobotDoctors.ToList();   

    // Create authors list for <select> dropdown 
    return tmp 
        .OrderBy(rb => rb.ModelNumber) 
        .Select(rb => new SelectListItem 
        { 
            Text = String.Format("{0}: {1}", rb.ModelNumber, rb.PreferredName), 
            Value = rb.RobotDoctorId.ToString(), 
            Selected = rb.RobotDoctorId == selected 
        }); 
} 

在前面的代码中,Create()方法之后添加了新的私有方法来完成获取数据的工作。 然后,Create()方法返回默认视图Create.cshtml,以显示一个输入表单。

接下来,我们还需要更新Create()方法的HttpPost版本。 该方法将在方法定义之上特别具有HttpPost属性。 用下面的代码更新这个Create()方法:

[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> Create([Bind("SocialSecurityNumber", "DateOfBirth", "FirstName", "LastName", "RobotDoctorId")] Human human) 
{ 
    if (ModelState.IsValid) 
    { 
        _context.Humans.Add(human); 
        await _context.SaveChangesAsync(); 
        return RedirectToAction("Index"); 
    } 
    return View(human); 
} 

另一件要注意的事情是Create()方法参数列表中的Bind属性。 该属性帮助我们准确地确定希望将哪个模型属性绑定到相应的表单字段。

最后,让我们用以下代码更新Edit()方法,从HttpGet版本开始。 与Create()方法一样,HttpGet版本不需要在其上面有任何属性来指示控制器方法使用的 HttpVerb:

public async Task<IActionResult> Edit(int? id) 
{ 
    if (id == null) 
    { 
        return NotFound(); 
    } 

    Human human = _context.Humans.Single(m => m.ID == id); 
    if (human == null) 
    { 
        return NotFound(); 
    } 

    ViewBag.RobotDoctors = GetListOfRobotDoctors(); 
    return View(human); 
} 

对这个Edit()方法的主要更改是添加了一个名为RobotDoctors的动态ViewBag属性,与Create()方法中所看到的类似。 它使用相同的私有方法来获取RobotDoctors列表。 它将Human模型返回到视图Edit.cshtml,视图显示一个条目表单来编辑现有的Human条目。

最后,让我们更新Edit()方法的HttpPost版本。 用以下代码替换此方法,以确保Human模型更新为已传递的数据:

[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> Edit(int id, [Bind("SocialSecurityNumber", "DateOfBirth", "FirstName", "LastName", "RobotDoctorId")] Human human) 
{ 
    if (id != human.ID) 
    { 
        return NotFound(); 
    } 

    if (ModelState.IsValid) 
    { 
        human.ID = id; 
        _context.Humans.Attach(human); 
        _context.Entry(human).State = EntityState.Modified; 
        await _context.SaveChangesAsync(); 
        return RedirectToAction("Index"); 
    } 
    return View(human); 

} 

为了通知 EF Core 修改的状态,将编辑条目的State属性设置为EntityState.Modified。 如果存在任何验证错误,则通过传入更新的Human模型,将用户定向到相同的Edit.cshtml视图。 如果没有验证错误,则将用户重定向到Index.cshtml视图,以显示Human条目的当前列表。

Delete()方法不需要任何额外的更改,因为实体代码生成负责正确删除每个实体。 当使用适当的控制器方法删除选定的Human时,它将显示一个由Delete()方法的HttpGet版本准备的确认屏幕。 一旦确认,Delete()方法的HttpPost版本将在调用SaveChanges()以相应更新数据库之前负责实际的删除。 在删除操作之后,用户被重定向到Index方法以查看Human条目列表。

更新视图

要完成编码更改,必须更新Human控制器的Views。 这些文件包括在Views文件夹中的Human子文件夹中的以下.cshtml文件:

  • 指数
  • 编辑
  • 细节
  • 创建

Index.cshtml文件中,添加以下表头<th>块,显示机器人医生的首选名称的标签,就在 SSN 标签之后:

<th> 
    @Html.DisplayNameFor(model => model.RobotDoctor.PreferredName) 
</th> 

foreach内循环遍历项目Model,<td>添加一个表数据块显示名字,SSN 之后字段,用于存储一个独特的社会安全号码。 这应该正好在编辑细节删除链接之前:

<td> 
    @Html.DisplayFor(modelItem => item.RobotDoctor.PreferredName) 
</td> 

Edit.cshtml文件中,更新<form>标记以包含额外的标记帮助器属性:

<form  
    asp-controller="Human"  
    asp-action="Edit"  
    method="post"  
    asp-route-id="@Model.ID"> 

这些属性的用途有很多:

  • asp-controllerasp-action:这表示将表单提交到的控制器名称和方法
  • method:表示提交表单的方法,通常为POST
  • asp-route-id:表示要与提交关联的 ID 值

在表单验证摘要的下方,删除隐藏的 ID 字段:

<input type="hidden" asp-for="ID" /> 

相反,用下面的代码替换它:

<div class="form-group"> 
    <label  
        asp-for="RobotDoctorId"  
        class="col-md-2 control-label"></label> 
    <div class="col-md-10"> 
        <select  
                asp-for="RobotDoctorId"  
                asp-items="@ViewBag.RobotDoctors"></select> 
    </div> 
</div> 

前面的代码显示了RobotDoctorId字段的标签,后面是RobotDoctors的下拉框。 您可能还记得,正在多个控制器方法中设置ViewBag.RobotDoctors的值。

Details.cshtml文件中,在<dt>/<dd>对块中添加以下描述列表条目,以显示每个机器人医生的编号、型号和首选名称的标签和字段,就在 SSN 标签的右侧:

<dt> 
    @Html.DisplayNameFor(model => model.RobotDoctor.RobotDoctorId) 
</dt> 
<dd> 
    @Html.DisplayFor(model => model.RobotDoctor.RobotDoctorId) 
</dd> 
<dt> 
    @Html.DisplayNameFor(model => model.RobotDoctor.ModelNumber) 
</dt> 
<dd> 
    @Html.DisplayFor(model => model.RobotDoctor.ModelNumber) 
</dd> 
<dt> 
    @Html.DisplayNameFor(model => model.RobotDoctor.PreferredName) 
</dt> 
<dd> 
    @Html.DisplayFor(model => model.RobotDoctor.PreferredName) 
</dd> 

前面的条目应该在关闭</dl>列表之前添加。

Edit视图类似,您必须使用新标签和下拉菜单更新Create视图,以显示RobotDoctors列表。 在表单中的验证摘要下面,添加以下表单组:

<div class="form-group"> 
    <label  
        asp-for="RobotDoctorId"  
        class="col-md-2 control-label"></label> 
  <div class="col-md-10"> 
    <select  
        asp-for="RobotDoctorId"  
        asp-items="@ViewBag.RobotDoctors"></select> 
  </div> 
</div> 

再一次,在适当的控制器方法中设置了ViewBag.RobotDoctors的动态值。 现在已经对模型、控制器和视图进行了所有必要的更改,现在可以使用 EF Migrations 更新数据库了。

EF Code First 迁移,用于数据库版本控制和维护

在 EF 中,您可以使用迁移来促进数据库的创建、升级和降级。 您还可以使用自动生成的版本历史来跟踪更改,并与开发团队的其他成员保持同步。

我们之前已经在我们的示例项目中设置了迁移以便开始工作。 在本节中,我们将添加一个新的迁移,以反映我们在本章中所做的更改。

设置迁移

下面回顾一下我们之前如何为 EF 设置迁移。 再次强调,请记住您的 DNX 版本可能有所不同:

  1. 打开指向项目文件夹位置的命令提示符。
  2. 执行如下命令:
>dotnet restore
>dotnet build
>dotnet ef migrations add Initial
>dotnet ef database update

前面的命令不需要再次运行,因为您的初始迁移已经在第 3 章了解 MVC中创建。 相反,我们将运行额外的命令来创建一个新的迁移来表示对模型和数据库上下文的更改。

添加和删除迁移

当你添加一个新的迁移时,会发生以下几件事:

  • 在初始迁移文件下面的Migrations文件夹中将生成一个新的类文件。 文件名通常以日期/时间戳作为前缀,然后是迁移的名称,例如2016MMDDXXYY_RobotDoctors.cs.
  • 迁移文件的内容将包含一个带有迁移名称的类,例如RobotDoctors。 这个类将包含两个方法Up()Down(),分别帮助数据库的升级和降级。
  • 一个自动生成的快照文件将被更新,以反映数据库模型和关系的当前状态。 文件名通常以数据库上下文的名称作为前缀,例如ApplicationDbContextModelSnapshot.cs
  • 在运行 update 命令之后,将使用适当的更改更新物理数据库。 如果由于某种原因无法成功处理更改,将返回一个或多个错误消息。

要添加新的迁移,请在项目文件夹位置的命令提示符中运行以下命令:

>dotnet restore
>dotnet build
>dotnet ef migrations add RobotDoctors
>dotnet ef database update

这将生成一个新的迁移,如前所述。 如果您得到任何数据库冲突错误,您可能必须首先删除Humans表中的记录,然后重新运行数据库更新命令。 现在可以检查数据库以检查新的更改。 为了快速找到数据库,使用SQL Server Object Explorer面板钻到你的数据库并检查表和字段。

后退一步,您可以使用remove命令删除之前的迁移。 完整的命令列表如下:

  • add:这将添加一个新的迁移
  • apply:这将把迁移应用到数据库
  • list:这将显示迁移列表
  • script:这将生成一个 SQL 脚本列表,而不需要实际更新数据库
  • remove:这将删除之前的迁移

值得注意的是,脚本命令类似于 EF 以前版本中的脚本参数。 不再将此特性隐藏在参数中(如果忘记包含它,可能会意外覆盖数据库),现在有单独的命令来更新数据库或只生成 SQL 脚本,而不更改任何内容。

运行应用

现在已经使用新的迁移完成了所有必要的数据库更改,现在可以运行应用了。 在 Visual Studio 2015 中构建解决方案并运行应用。 这将从Home控制器启动默认的 web 浏览器,主Index页面,如下截图所示:

<graphics/image_06_004.jpg>

在顶部菜单中,点击Humans链接,可查看Human控制器的Index页面。 这将显示一个空列表,因为此时我们还没有创建任何新的Humans。 如果您在进入此步骤之前已经创建了自己的条目,请在继续之前删除您的条目。

下图为Human控制器Index界面:

<graphics/image_06_005.jpg>

为了确保我们有一些示例数据,打开RobotDoctors表,并使用 Visual Studio 中的SQL Server 对象管理器手动添加一些条目到数据库中。 下面的截图显示了RobotDoctorIdModelNumberPreferredName的一些示例值:

| ***RobotDoctorId (auto)*** | ***ModelNumber*** | ***PreferredName*** | | 1 | 90210 | X 博士 | | 2 | 12345 | 芝加哥博士 |

我们可以写一些额外的代码来添加种子数据到你的数据库中,但我们将把这一步保存到第 7 章依赖注入和健壮 Web 应用的单元测试中。 最好使用一个测试框架来添加种子数据,而不是将其添加到应用代码中。

回到您的 web 浏览器,单击左上角区域中的Create New链接,查看HumanControllerCreate视图。 选择一个机器人医生,然后完成并提交表单,创建一个新的人类条目。 如果有任何验证错误,将提示您在提交完成之前更正它们。 一旦提交,你应该被重定向到Index页。 Create视图如下截图所示:

<graphics/image_06_006.jpg>

在下面的截图中,在Index页面上,你应该看到标签为EditDetails,andDelete的链接。 让我们试试这些链接来编辑条目,查看条目的详细信息,或删除现有条目:

<graphics/image_06_007.jpg>

如果您单击Edit链接,您现在应该看到先前添加条目的可编辑详细信息,如下面的截图所示。 更改一些值并提交表单。 与创建新条目类似,您将被提示修复任何验证错误,或者在提交时返回Index页面:

<graphics/image_06_008.jpg>

如果您单击Details链接,您应该看到先前添加条目的不可编辑详细信息,如下面的截图所示。 您可以选择再次返回Index页面或单击Edit查看可编辑视图:

<graphics/image_06_009.jpg>

如果您点击Delete链接,您将看到一个确认页面,询问您是否要删除该条目,如下面的截图所示。 点击删除按钮继续或返回Index页面:

<graphics/image_06_010.jpg>

总结

在这一章中,我们讨论了 EF Core,它是一个用于 web 应用的现代 ORM 工具。 出于本书的目的,我们只讨论了 EF Core 与 ASP 的关系。 净的核心。 关于 EF Core 的更多信息,您可以查看官方文档https://ef.readthedocs.org

在下一章中,您将涵盖依赖注入反转控制单元测试。 这将为您提供良好的应用设计基础,以确保您拥有健壮的、可测试的应用,这些应用可以放心地轻松更新。*****

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值