ASP.NET MVC – 快速指南

ASP.NET MVC – 快速指南


ASP.NET MVC – 概述

ASP.NET MVC 基本上是一个来自微软的 web 开发框架,它结合了 MVC(Model-View-Controller)架构的特点,敏捷开发的最新思想和技术,以及现有 ASP 的最佳部分.NET 平台。

ASP.NET MVC 不是从零开始构建的东西。它是传统 ASP.NET Web 窗体的完整替代品。它构建在 ASP.NET 之上,因此开发人员可以在构建 MVC 应用程序时享受几乎所有 ASP.NET 功能。

构建 MVC 应用程序

历史

ASP.NET 1.0 于 2002 年 1 月 5 日发布,作为 .Net Framework 1.0 版的一部分。当时,很容易将 ASP.NET 和 Web 窗体视为一回事。然而,ASP.NET 一直支持两层抽象 –

  • System.Web.UI – Web 窗体层,包括服务器控件、ViewState 等。

  • System.Web – 它提供基本的 Web 堆栈,包括模块、处理程序、HTTP 堆栈等。

到 2007 年 ASP.NET MVC 发布时,MVC 模式已成为构建 Web 框架最流行的方式之一。

2009 年 4 月,ASP.NET MVC 源代码在 Microsoft 公共许可证 (MS-PL) 下发布。“ASP.NET MVC 框架是一个轻量级、高度可测试的表示框架,它与现有的 ASP.NET 功能集成在一起。

其中一些集成功能是母版页和基于成员资格的身份验证。MVC 框架在 System.Web.Mvc 程序集中定义。

2012 年 3 月,微软在开源许可(Apache License 2.0)下发布了部分网络堆栈(包括 ASP.NET MVC、Razor 和 Web API)。ASP.NET Web 窗体未包含在此计划中。

为什么是 ASP.NET MVC?

Microsoft 决定创建自己的 MVC 框架来构建 Web 应用程序。MVC 框架只是建立在 ASP.NET 之上。当您使用 ASP.NET MVC 构建 Web 应用程序时,不会有状态幻觉,不会有页面加载和页面生命周期等情况。

ASP.NET MVC 的另一个设计目标是可扩展到框架的所有方面。因此,当我们谈论视图时,视图必须由特定类型的视图引擎呈现。默认视图引擎仍然可以采用 ASPX 文件。但是如果您不喜欢使用 ASPX 文件,您可以使用其他东西并插入您自己的视图引擎。

MVC 框架中有一个组件可以实例化您的控制器。您可能不喜欢 MVC 框架实例化控制器的方式,您可能希望自己处理这项工作。因此,MVC 中有很多地方可以注入您自己的自定义逻辑来处理任务。

使用模型视图控制器设计模式背后的整个想法是保持关注点分离。您的控制器不再受与 ASP.NET 运行时或与 ASPX 页面的大量联系所困扰,这很难测试。您现在只有一个带有常规方法的类,您可以在单元测试中调用它来确定该控制器是否会正确运行。

ASP.NET MVC 的好处

以下是使用 ASP.NET MVC 的好处 –

  • 通过将应用程序划分为模型、视图和控制器,可以更轻松地管理复杂性。

  • 启用对呈现的 HTML 的完全控制并提供清晰的关注点分离。

  • 对 HTML 的直接控制还意味着更好的可访问性,以实现对不断发展的 Web 标准的遵从性。

  • 有助于为现有应用程序添加更多交互性和响应性。

  • 为测试驱动开发 (TDD) 提供更好的支持。

  • 适用于由大型开发人员团队支持的 Web 应用程序以及需要高度控制应用程序行为的 Web 设计人员。

ASP.NET MVC – 模式

MVC(模型-视图-控制器)设计模式实际上已经存在了几十年,它被用于许多不同的技术。从 Smalltalk 到 C++ 再到 Java,现在的 C Sharp 和 .NET 都使用这种设计模式来构建用户界面。

以下是 MVC 模式的一些显着特征 –

  • 1979年最初命名为Thing-Model-View-Editor,后简化为Model-View-Controller。

  • 它是一种在应用程序中分离关注点的强大而优雅的方法(例如,将数据访问逻辑与显示逻辑分离),并且非常适用于 Web 应用程序。

  • 其明确的关注点分离确实为应用程序的设计增加了少量额外的复杂性,但其非凡的好处超过了额外的努力。

MVC 架构模式将应用程序的用户界面 (UI) 分为三个主要部分。

MVC架构模式

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

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

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

MVC 背后的想法

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

视图与模型对话,该模型包含视图需要显示的所有数据。视图内部通常根本没有太多逻辑。

在 Web 应用程序中,视图可能根本没有任何与之关联的代码。它可能只有 HTML,然后是一些表达式,用于从模型中获取数据片段并将它们插入到您在视图中构建的 HTML 模板中的正确位置。

组织的控制器就是一切。当 MVC 应用程序的 HTTP 请求到达时,该请求被路由到控制器,然后由控制器与数据库、文件系统或模型进行对话。

ASP.NET MVC – 环境设置

MVC 开发工具包含在 Visual Studio 2012 及更高版本中。它也可以安装在 Visual Studio 2010 SP1/Visual Web Developer 2010 Express SP1 上。如果您使用的是 Visual Studio 2010,则可以使用 Web 平台安装程序http://www.microsoft.com安装 MVC 4

Microsoft 提供了一个免费版本的 Visual Studio,其中也包含 SQL Server,可以从https://www.visualstudio.com下载

安装

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

运行安装程序

步骤 2 – 单击“安装”按钮,它将开始安装过程。

安装过程

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

安装过程完成

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

第 4 步– 从开始菜单打开 Visual Studio,这将打开以下对话框。第一次只为准备需要一段时间。

打开 Visual Studio

完成所有操作后,您将看到 Visual Studio 的主窗口,如下面的屏幕截图所示。

Visual Studio 主窗口

您现在可以开始您的应用程序了。

ASP.NET MVC – 入门

在本章中,我们将看一个简单的 ASP.NET MVC 工作示例。我们将在这里构建一个简单的 Web 应用程序。要创建 ASP.NET MVC 应用程序,我们将使用 Visual Studio 2015,它包含创建、测试和部署 MVC 框架应用程序所需的所有功能。

创建 ASP.Net MVC 应用程序

以下是使用 Visual Studio 中可用的项目模板创建项目的步骤。

步骤 1 – 打开 Visual Studio。单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

项目菜单选项

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

步骤 4 – 在名称字段中输入项目名称 MVCFirstApp,然后单击确定继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

输入项目名称

第 5 步– 为简单起见,请选择“空”选项并选中“添加文件夹和核心参考”部分中的 MVC 复选框。单击确定。

它将创建一个具有最少预定义内容的基本 MVC 项目。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。

创建 ASP.Net MVC 项目

如您所知,我们已经从一个空的项目模板创建了 ASP.Net MVC 项目,因此目前该应用程序不包含任何要运行的内容。

第 6 步– 从 Debug → Start Debugging 菜单选项运行此应用程序,您将看到404 Not Found错误。

404未找到错误

默认浏览器是 Internet Explorer,但您可以从工具栏中选择已安装的任何浏览器。

添加控制器

为了消除 404 Not Found 错误,我们需要添加一个控制器,它处理所有传入的请求。

步骤 1 – 要添加控制器,请右键单击解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

添加控制器

它将显示“添加脚手架”对话框。

控制器脚手架对话框

第 2 步– 选择 MVC 5 控制器 – 空选项,然后单击“添加”按钮。

将出现添加控制器对话框。

添加控制器对话框

第 3 步– 将名称设置为 HomeController 并单击添加按钮。

您将在 Controllers 文件夹中看到一个新的 C# 文件 HomeController.cs,该文件夹也已打开以在 Visual Studio 中进行编辑。

C# 主控制器

第 4 步– 为了使其成为一个工作示例,让我们通过使用以下代码更改名为Index的操作方法来修改控制器类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCFirstApp.Controllers {
   public class HomeController : Controller {
      // GET: Home
      public string Index(){
         return "Hello World, this is ASP.Net MVC Tutorials";
      }
   }
}

第 5 步– 运行此应用程序,您将看到浏览器正在显示 Index 操作方法的结果。

索引操作方法

ASP.NET MVC – 生命周期

在本章中,我们将讨论整个 MVC 管道以及 HTTP 请求通过 ASP.NET 中的 MVC 框架时的生命周期。在高层次上,生命周期只是用于处理某种类型的请求或更改应用程序状态的一系列步骤或事件。您可能已经熟悉各种框架生命周期,这个概念并不是 MVC 独有的。

例如,ASP.NET webforms 平台具有复杂的页面生命周期。其他 .NET 平台(如 Windows 手机应用程序)有自己的应用程序生命周期。无论采用何种技术,所有这些平台都适用的一件事是,了解处理管道可以帮助您更好地利用可用功能,MVC 也不例外。

MVC 有两个生命周期 –

  • 应用程序生命周期
  • 请求生命周期

MVC 生命周期

应用程序生命周期

应用程序生命周期是指应用程序进程实际开始运行 IIS 直到它停止的时间。这由应用程序启动文件中的应用程序开始和结束事件标记。

请求生命周期

它是我们的应用程序每次处理 HTTP 请求时发生的事件序列。

每个 MVC 应用程序的入口点都从路由开始。在 ASP.NET 平台收到请求后,它会通过 URL 路由模块确定应该如何处理它。

模块是 .NET 组件,可以连接到应用程序生命周期并添加功能。路由模块负责将传入的 URL 与我们在应用程序中定义的路由进行匹配。

所有路由都有一个关联的路由处理程序,这是 MVC 框架的入口点。

路由处理程序

MVC 框架处理将路由数据转换为可以处理请求的具体控制器。创建控制器后,下一个主要步骤是Action Execution称为动作调用器的组件会查找并选择合适的 Action 方法来调用控制器。

准备好我们的动作结果后,将触发下一阶段,即Result ExecutionMVC 将声明结果与执行结果分开。如果结果是视图类型,则视图引擎将被调用并负责查找和渲染我们的视图。

如果结果不是视图,则操作结果将自行执行。此结果执行生成对原始 HTTP 请求的实际响应。

ASP.NET MVC – 路由

路由是将 HTTP 请求定向到控制器的过程,此处理的功能在 System.Web.Routing 中实现。此程序集不是 ASP.NET MVC 的一部分。它实际上是 ASP.NET 运行时的一部分,它作为 .NET 3.5 SP1 与 ASP.NET 一起正式发布。

System.Web.Routing由 MVC 框架使用,但它也由 ASP.NET 动态数据使用。MVC 框架利用路由将请求定向到控制器。Global.asax 文件是应用程序的一部分,您将在其中定义应用程序的路由。

这是来自我们在上一章中创建的 MVC 应用程序的 Global.asax 中的应用程序启动事件的代码。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFirstApp {
   public class MvcApplication : System.Web.HttpApplication {
      protected void Application_Start(){
         AreaRegistration.RegisterAllAreas();
         RouteConfig.RegisterRoutes(RouteTable.Routes);
      }
   }
}

下面是 RouteConfig 类的实现,它包含一个方法 RegisterRoutes。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFirstApp {
   public class RouteConfig {
      public static void RegisterRoutes(RouteCollection routes){
         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
         routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new{ controller = "Home", action = "Index", id = UrlParameter.Optional});
      }
   }
}

您将定义路由,这些路由会将 URL 映射到特定的控制器操作。动作只是控制器上的一个方法。它还可以从该 URL 中挑选参数并将它们作为参数传递到方法中。

所以这个在应用中定义的路由就是默认路由。如上代码所示,当你看到一个URL以(something)/(something)/(something)的形式到达时,那么第一块是控制器名称,第二块是动作名称,第三块是一个 ID 参数。

了解路线

MVC 应用程序使用 ASP.NET 路由系统,该系统决定 URL 如何映射到控制器和操作。

当 Visual Studio 创建 MVC 项目时,它会添加一些默认路由来让我们开始。当您运行您的应用程序时,您将看到 Visual Studio 已将浏览器定向到端口 63664。您几乎肯定会在浏览器请求的 URL 中看到不同的端口号,因为 Visual Studio 在创建项目时分配了一个随机端口。

本地主机主页

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

http://localhost:63664/Home/

http://localhost:63664/Home/Index

当浏览器请求 http://mysite/ 或 http://mysite/Home 时,它​​会从 HomeController 的 Index 方法获取输出。

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

如果您将 /Home 或 /Home/Index 附加到 URL 并按“Enter”按钮,您将看到来自 MVC 应用程序的相同结果。

本地主机主页索引

正如您在本例中看到的,约定是我们有一个名为 HomeController 的控制器,这个 HomeController 将成为我们 MVC 应用程序的起点。

Visual Studio 为新项目创建的默认路由假定您将遵循此约定。但是,如果您想遵循自己的约定,则需要修改路由。

自定义约定

您当然可以添加自己的路线。如果您不喜欢这些操作名称,如果您有不同的 ID 参数,或者您的站点通常具有不同的 URL 结构,那么您可以添加自己的路由条目。

我们来看一个简单的例子。考虑我们有一个包含进程列表的页面。以下是代码,它将路由到流程页面。

routes.MapRoute(
   "Process",
   "Process/{action}/{id}",
   defaults: new{
      controller = "Process", action = "List ", id = UrlParameter.Optional}
);

当有人进来寻找带有 Process/Action/Id 的 URL 时,他们将转到 Process Controller。我们可以让动作有点不同,默认动作,我们可以把它变成一个列表而不是索引。

现在到达的请求看起来像 localhosts/process。路由引擎将使用此路由配置来传递它,因此它将使用 List 的默认操作。

以下是完整的类实现。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFirstApp{
   public class RouteConfig{
      public static void RegisterRoutes(RouteCollection routes){
         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
			
         routes.MapRoute(
            "Process", "Process/{action}/{id}",
            defaults: new{
               controller = " Process", action = "List ", id =
               UrlParameter.Optional});
					
         routes.MapRoute(
            name: "Default", url: "{controller}/{action}/{id}",
            defaults: new{
               controller = "Home", action = "Index", id =
               UrlParameter.Optional});
      }
   }
}

第 1 步– 运行此程序并使用以下 URL http://localhost:63664/Process请求流程页面

本地主机进程

您将看到 HTTP 404,因为路由引擎正在寻找 ProcessController,但它不可用。

第 2 步– 通过右键单击解决方案资源管理器中的 Controllers 文件夹并选择添加 → 控制器来创建 ProcessController。

创建进程控制器

它将显示“添加脚手架”对话框。

ProcessController 脚手架对话框

步骤 3 – 选择 MVC 5 Controller – Empty 选项,然后单击“添加”按钮。

将出现添加控制器对话框。

空选项添加按钮

第 4 步– 将名称设置为 ProcessController 并单击“添加”按钮。

现在,您将在 Controllers 文件夹中看到一个新的 C# 文件 ProcessController.cs,该文件夹也已打开以在 Visual Studio 中进行编辑。

设置进程控制器

现在我们的默认操作将是 List,所以我们希望这里有一个 List 操作而不是 Index。

第 5 步– 将返回类型从 ActionResult 更改为字符串,并使用以下代码从此操作方法返回一些字符串。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFirstApp.Controllers{
   public class ProcessController : Controller{
      // GET: Process
      public string List(){
         return "This is Process page";
      }
   }
}

步骤 6 – 当您运行此应用程序时,您将再次看到默认路由的结果。当您指定以下 URL http://localhost:63664/Process/List 时,您将看到来自 ProcessController 的结果。

本地主机进程列表

ASP.NET MVC – 控制器

控制器本质上是 ASP.NET MVC 应用程序的中心单元。它是第一个接收者,它与传入的 HTTP 请求交互。因此,控制器决定将选择哪个模型,然后在渲染该视图之后,从模型中获取数据并将其传递给相应的视图。实际上,控制器正在控制应用程序的整体流程,获取输入并呈现正确的输出。

控制器是从 System.Web.Mvc.Controller 继承的 C# 类,它是内置的控制器基类。控制器中的每个公共方法都称为操作方法,这意味着您可以通过某个 URL 从 Web 调用它来执行操作。

MVC 约定是将控制器放在 Visual Studio 在设置项目时创建的 Controllers 文件夹中。

让我们通过创建一个新的 ASP.Net MVC 项目来看看 Controller 的一个简单示例。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

Visual Studio 项目菜单

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称“MVCControllerDemo”,然后单击确定继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVCControllerDemo

第 5 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。

它将创建一个具有最少预定义内容的基本 MVC 项目。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。

由于我们已经从一个空的项目模板创建了 ASP.Net MVC 项目,所以目前,该应用程序不包含任何要运行的内容。

第 6 步– 通过右键单击解决方案资源管理器中的 Controllers 文件夹添加 EmployeeController。选择添加 → 控制器。

员工控制器

它将显示“添加脚手架”对话框。

EmployeeController 脚手架对话框

步骤 7 – 选择 MVC 5 Controller – Empty 选项,然后单击“添加”按钮。

将出现添加控制器对话框。

MVC 5 控制器

步骤 8 – 将名称设置为 EmployeeController 并单击“添加”按钮。

您将在 Controllers 文件夹中看到一个新的 C# 文件 EmployeeController.cs,该文件夹也已打开以在 Visual Studio 中进行编辑。

自定义路由员工控制器

现在,在这个应用程序中,我们将使用默认路由为 Employee 控制器添加一个自定义路由。

步骤 1 – 转到“App_Start”文件夹下的“RouteConfig.cs”文件并添加以下路由。

routes.MapRoute(
   "Employee", "Employee/{name}", new{
      controller = "Employee", action = "Search", name =
      UrlParameter.Optional });

以下是 RouteConfig.cs 文件的完整实现。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCControllerDemo {
   public class RouteConfig {
      public static void RegisterRoutes(RouteCollection routes){
         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
			
         routes.MapRoute(
            "Employee", "Employee/{name}", new{
               controller = "Employee", action = "Search", name = UrlParameter.Optional });
					
         routes.MapRoute(
            name: "Default", url: "{controller}/{action}/{id}", defaults: new{
               controller = "Home", action = "Index", id = UrlParameter.Optional });
      }
   }
}

考虑一个场景,其中任何用户都来搜索员工,并指定 URL“Employee/Mark”。在这种情况下,Mark 将被视为参数名称,而不是 Action 方法。所以在这种情况下,我们的默认路由不会显着工作。

为了在传递参数时从浏览器获取传入值,MVC 框架提供了一种简单的方法来解决这个问题。它是通过使用 Action 方法中的参数来实现的。

第 2 步– 使用以下代码更改 EmployeeController 类。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers  {
   public class EmployeeController : Controller {
      // GET: Employee
      public ActionResult Search(string name){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
   }
}

如果向操作方法添加参数,则 MVC 框架将查找与参数名称匹配的值。它将应用所有可能的组合来找出参数值。它将在路由数据、查询字符串等中进行搜索。

因此,如果您请求 /Employee/Mark”,那么 MVC 框架将决定我需要一个带有“UserInput”的参数,然后 Mark 将从 URL 中选取并自动传递。

Server.HtmlEncode 将简单地以纯文本形式转换任何类型的恶意脚本。当上述代码编译执行并请求以下 URL http://localhost:61465/Employee/Mark 时,您将得到以下输出。

本地主机员工标记

正如您在上面的屏幕截图中看到的,Mark 是从 URL 中选取的。

ASP.NET MVC – 操作

ASP.NET MVC Action Methods 负责执行请求并生成响应。默认情况下,它以 ActionResult 的形式生成响应。操作通常与用户交互具有一对一的映射关系。

例如,在浏览器中输入 URL,单击任何特定链接,然后提交表单等。这些用户交互中的每一个都会导致向服务器发送请求。在每种情况下,请求的 URL 都包含 MVC 框架用来调用操作方法的信息。action 方法的一个限制是它们必须是实例方法,所以它们不能是静态方法。也没有返回值限制。所以你可以返回字符串、整数等。

请求处理

动作是 MVC 应用程序中的最终请求目的地,它使用控制器基类。我们来看看请求处理。

  • 当 URL 到达时,例如 /Home/index,UrlRoutingModule 会检查并了解路由表中配置的某些内容知道如何处理该 URL。

请求处理

  • UrlRoutingModule 将我们在路由表中配置的信息放在一起,并将控制权移交给 MVC 路由处理程序。

  • MVC 路由处理程序将控制器传递给 MvcHandler,它是一个 HTTP 处理程序。

  • MvcHandler 使用控制器工厂来实例化控制器,它知道要实例化哪个控制器,因为它会在 RouteData 中查找该控制器值。

  • 一旦 MvcHandler 有了控制器,MvcHandler 唯一知道的是 IController 接口,所以它只是告诉控制器执行。

  • 当它告诉控制器执行时,它派生自 MVC 的控制器基类。Execute 方法创建一个动作调用程序并告诉该动作调用程序去寻找要调用的方法,找到要调用的动作。

  • 动作调用程序再次查看 RouteData 并找到从路由引擎传递过来的动作参数。

行动类型

动作基本上返回不同类型的动作结果。ActionResult 类是所有操作结果的基础。以下是不同类型的操作结果及其行为的列表。

Sr.No. 名称和行为
1

ContentResult

返回一个字符串

2

FileContentResult

返回文件内容

3

FilePathResult

返回文件内容

4

FileStreamResult

返回文件内容

5

EmptyResult

什么都不返回

6

JavaScriptResult

返回执行脚本

7

JsonResult

返回 JSON 格式的数据

8

RedirectToResult

重定向到指定的 URL

9

HttpUnauthorizedResult

返回 403 HTTP 状态码

10

RedirectToRouteResult

重定向到不同的动作/不同的控制器动作

11

ViewResult

作为视图引擎的响应接收

12

PartialViewResult

作为视图引擎的响应接收

让我们看一下上一章中创建的 EmployeeController 的一个简单示例。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      public ActionResult Search(string name){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
   }
}

当您请求以下 URL http://localhost:61465/Employee/Mark 时,您将收到以下输出作为操作。

本地主机员工标记输出

添加控制器

让我们再添加一个控制器。

步骤 1 – 右键单击​​ Controllers 文件夹并选择添加 → 控制器。

添加另一个控制器

它将显示“添加脚手架”对话框。

添加脚手架对话框

第 2 步– 选择 MVC 5 控制器 – 空选项,然后单击“添加”按钮。

将出现添加控制器对话框。

客户控制器

第 3 步– 将名称设置为 CustomerController 并单击“添加”按钮。

现在,您将在 Controllers 文件夹中看到一个新的 C# 文件“CustomerController.cs”,该文件也已打开以在 Visual Studio 中进行编辑。

set_name CustomerController

同样,再添加一个名为 HomeController 的控制器。以下是 HomeController.cs 类实现。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public string Index(){
         return "This is Home Controller";
      }
   }
}

第 4 步– 运行此应用程序,您将收到以下输出。

家庭控制器输出

第 5 步– 在我们上面创建的 Customer 控制器中添加以下代码。

public string GetAllCustomers(){
   return @"<ul>
      <li>Ali Raza</li>
      <li>Mark Upston</li>
      <li>Allan Bommer</li>
      <li>Greg Jerry</li>
   </ul>";
}

第 6 步– 运行此应用程序并请求http://localhost:61465/Customer/GetAllCustomers您将看到以下输出。

本地主机 GetAllCustomers

您还可以重定向到同一控制器甚至不同控制器的操作。

以下是一个简单的示例,我们将通过使用以下代码更改 HomeController 中的代码,从 HomeController 重定向到 Customer Controller。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers{
   public class HomeController : Controller{
      // GET: Home
      public ActionResult Index(){
         return RedirectToAction("GetAllCustomers","Customer");
      }
   }
}

如您所见,我们使用了 RedirectToAction() 方法 ActionResult,它接受两个参数,动作名称和控制器名称。

当您运行此应用程序时,您将看到默认路由会将其重定向到 /Customer/GetAllCustomers

本地主机客户 GetAllCustomers

ASP.NET MVC – 过滤器

在 ASP.NET MVC 中,控制器定义通常与可能的用户交互具有一对一关系的操作方法,但有时您希望在调用操作方法之前或操作方法运行之后执行逻辑。

为了支持这一点,ASP.NET MVC 提供了过滤器。过滤器是自定义类,它提供声明性和编程方式来向控制器操作方法添加操作前和操作后行为。

动作过滤器

操作过滤器是一种属性,您可以将其应用于控制器操作或整个控制器,用于修改操作的执行方式。ASP.NET MVC 框架包括几个动作过滤器 –

  • OutputCache – 在指定的时间内缓存控制器操作的输出。

  • HandleError – 处理执行控制器操作时引发的错误。

  • 授权– 使您能够限制对特定用户或角色的访问。

过滤器类型

ASP.NET MVC 框架支持四种不同类型的过滤器 –

  • 授权过滤器– 实现 IAuthorizationFilter 属性。

  • 动作过滤器– 实现 IActionFilter 属性。

  • 结果过滤器– 实现 IResultFilter 属性。

  • 异常过滤器– 实现 IExceptionFilter 属性。

过滤器按上面列出的顺序执行。例如,授权过滤器总是在动作过滤器之前执行,异常过滤器总是在所有其他类型的过滤器之后执行。

授权过滤器用于实现控制器动作的身份验证和授权。例如,授权过滤器是授权过滤器的一个示例。

让我们通过创建一个新的 ASP.Net MVC 项目来看看一个简单的例子。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

新项目菜单选项

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称 MVCFiltersDemo,然后单击确定继续,您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVCFiltersDemo

第 5 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。

它将创建一个具有最少预定义内容的基本 MVC 项目。

步骤 6 – 要添加控制器,请右键单击解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

它将显示“添加脚手架”对话框。

控制器添加脚手架对话框

步骤 7 – 选择 MVC 5 Controller – Empty 选项,然后单击“添加”按钮。

将出现添加控制器对话框。

添加控制器对话框

第 8 步– 将名称设置为 HomeController,然后单击“添加”按钮。

您将在 Controllers 文件夹中看到一个新的 C# 文件“HomeController.cs”,该文件也已打开以在 Visual Studio 中进行编辑。

应用操作过滤器

动作过滤器可以应用于单个控制器动作或整个控制器。例如,操作过滤器OutputCache应用于名为 Index() 的操作,该操作返回字符串。此过滤器会使操作返回的值缓存 15 秒。

为了使它成为一个工作示例,让我们通过使用以下代码更改名为Index的操作方法来修改控制器类

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFiltersDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      [OutputCache(Duration = 15)]
		
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      }
   }
}

当您运行此应用程序时,您将看到浏览器正在显示 Index 操作方法的结果。

MVC 过滤器教程

让我们添加另一个动作方法,它将显示当前时间。

namespace MVCFiltersDemo.Controllers{
   public class HomeController : Controller{
      // GET: Home
		
      [OutputCache(Duration = 15)]
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      }
		
      [OutputCache(Duration = 20)]
      public string GetCurrentTime(){
         return DateTime.Now.ToString("T");
      }
   }
}

请求以下 URL,http://localhost:62833/Home/GetCurrentTime,您将收到以下输出。

本地主机获取当前时间

如果刷新浏览器,您将看到相同的时间,因为该操作已缓存 20 秒。当您在 20 秒后刷新它时,它将被更新。

自定义过滤器

为了创建您自己的自定义过滤器,ASP.NET MVC 框架提供了一个称为 ActionFilterAttribute 的基类。此类实现了 IActionFilter 和 IResultFilter 接口,并且两者均派生自 Filter 类。

让我们通过使用 ActionFilters 在您的项目中创建一个新文件夹来看看自定义过滤器的简单示例。添加一个类,右键单击 ActionFilters 文件夹并选择添加 → 类。

自定义过滤器

在名称字段中输入“MyLogActionFilter”,然后单击“添加”按钮。

这个类将从ActionFilterAttribute派生,它是一个基类并覆盖以下方法。以下是 MyLogActionFilter 的完整实现。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFiltersDemo.ActionFilters {
   public class MyLogActionFilter : ActionFilterAttribute{
      public override void OnActionExecuting(ActionExecutingContext filterContext){
         Log("OnActionExecuting", filterContext.RouteData);
      }
		
      public override void OnActionExecuted(ActionExecutedContext filterContext){
         Log("OnActionExecuted", filterContext.RouteData);
      }
		
      public override void OnResultExecuting(ResultExecutingContext filterContext){
         Log("OnResultExecuting", filterContext.RouteData);
      }
		
      public override void OnResultExecuted(ResultExecutedContext filterContext){
         Log("OnResultExecuted", filterContext.RouteData);
      }
		
      private void Log(string methodName, RouteData routeData){
         var controllerName = routeData.Values["controller"];
         var actionName = routeData.Values["action"];
			
         var message = String.Format(
            "{0} controller:{1} action:{2}", methodName, controllerName, actionName);
				
         Debug.WriteLine(message, "Action Filter Log");
      }
   }
}

现在让我们使用以下代码将日志过滤器应用于 HomeController。

using MVCFiltersDemo.ActionFilters;
using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFiltersDemo.Controllers {
   [MyLogActionFilter]
   public class HomeController : Controller{
      // GET: Home
		
      [OutputCache(Duration = 10)]
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      }
		
      [OutputCache(Duration = 10)]
      public string GetCurrentTime(){
         return DateTime.Now.ToString("T");
      }
   }
}

运行应用程序,然后观察输出窗口。

输出窗口

如上面的屏幕截图所示,处理操作的阶段会记录到 Visual Studio 输出窗口中。

ASP.NET MVC – 选择器

动作选择器是可以应用于动作方法的属性,用于影响响应请求而调用的动作方法。它帮助路由引擎选择正确的操作方法来处理特定请求。

当您编写操作方法时,它起着非常关键的作用。这些选择器将根据操作方法前面给出的修改名称来决定方法调用的行为。它通常用于为操作方法的名称取别名。

有三种类型的动作选择器属性 –

  • 动作名称
  • 非行动
  • 行为动词

动作名称

此类表示用于操作名称的属性。它还允许开发人员使用与方法名称不同的操作名称。

让我们看一下上一章的一个简单示例,其中 HomeController 包含两个操作方法。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFiltersDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      } 
		
      public string GetCurrentTime(){
         return DateTime.Now.ToString("T");
      }
   }
}

让我们通过在 GetCurrentTime() 上方写入 [ActionName(“CurrentTime”)] 来为 GetCurrentTime 应用 ActionName 选择器,如下面的代码所示。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFiltersDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      }
		
      [ActionName("CurrentTime")]
      public string GetCurrentTime(){
         return DateTime.Now.ToString("T");
      }
   }
}

现在运行此应用程序并在浏览器中输入以下 URL http://localhost:62833/Home/CurrentTime,您将收到以下输出。

本地主机当前时间

可以看到我们使用了 CurrentTime 而不是原来的动作名称,即上面 URL 中的 GetCurrentTime。

非行动

NonAction 是另一个内置属性,它表示 Controller 的公共方法不是操作方法。当您希望方法不应被视为操作方法时使用它。

让我们看一个简单的例子,在 HomeController 中添加另一个方法,并使用以下代码应用 NonAction 属性。

using MVCFiltersDemo.ActionFilters;
using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFiltersDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public string Index(){
         return "This is ASP.Net MVC Filters Tutorial";
      }
		
      [ActionName("CurrentTime")]
      public string GetCurrentTime(){
         return TimeString();
      }
		
      [NonAction]
      public string TimeString(){
         return "Time is " + DateTime.Now.ToString("T");
      }
   }
}

新方法 TimeString 是从 GetCurrentTime() 调用的,但您不能将其用作 URL 中的操作。

让我们运行这个应用程序并在浏览器中指定以下 URL http://localhost:62833/Home/CurrentTime您将收到以下输出。

本地主机当前时间

现在让我们检查URL 中/TimeString as action,看看会发生什么。

时间字符串

您可以看到它给出了“404—未找到”错误。

行为动词

您可以应用的另一个选择器过滤器是 ActionVerbs 属性。因此,这将特定操作的指示限制为特定 HttpVerbs。您可以定义两个具有相同名称的不同操作方法,但一种操作方法响应 HTTP Get 请求,而另一种操作方法响应 HTTP Post 请求。

MVC 框架支持以下 ActionVerbs。

  • 获取
  • 邮局
  • HttpPut
  • 删除
  • HttpOptions
  • 补丁

让我们看一个简单的例子,我们将在其中创建 EmployeeController。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      public ActionResult Search(string name = “No name Entered”){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
   }
}

现在让我们使用以下代码添加另一个同名的操作方法。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      //public ActionResult Index()
      //{
         // return View();
      //}
		
      public ActionResult Search(string name){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
		
      public ActionResult Search(){
         var input = "Another Search action";
         return Content(input);
      }
   }
}

当你运行这个应用程序时,它会给出一个错误,因为 MVC 框架无法确定应该为请求选择哪个操作方法。

让我们使用以下代码将 HttpGet ActionVerb 指定为您想要的操作作为响应。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      //public ActionResult Index()
      //{
         // return View();
      //}
		
      public ActionResult Search(string name){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
		
      [HttpGet]
      public ActionResult Search(){
         var input = "Another Search action";
         return Content(input);
      }
   }
}

运行此应用程序时,您将收到以下输出。

另一个搜索操作

ASP.NET MVC – 视图

在 ASP.NET MVC 应用程序中,没有什么比页面更像,而且当您在 URL 中指定路径时,它也不包含与页面直接对应的任何内容。与 ASP.NET MVC 应用程序中的页面最接近的东西称为View

在 ASP.NET MVC 应用程序中,所有传入的浏览器请求都由控制器处理,并将这些请求映射到控制器操作。一个控制器动作可能会返回一个视图,也可能会执行一些其他类型的动作,例如重定向到另一个控制器动作。

让我们通过创建一个新的 ASP.NET MVC 项目来查看一个简单的 View 示例。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

视觉工作室

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称“MVCViewDemo”,然后单击“确定”继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVCViewDemo

第 5 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。

它将创建一个具有最少预定义内容的基本 MVC 项目。我们现在需要添加控制器。

步骤 6 – 右键单击​​解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

它将显示“添加脚手架”对话框。

控制器文件夹

步骤 7 – 选择 MVC 5 Controller – Empty 选项,然后单击“添加”按钮。

将出现添加控制器对话框。

添加控制器对话框

第 8 步– 将名称设置为 HomeController,然后单击“添加”按钮。

您将在 Controllers 文件夹中看到一个新的 C# 文件“HomeController.cs”,该文件也已打开以在 Visual Studio 中进行编辑。

让我们更新 HomeController.cs 文件,其中包含两个操作方法,如以下代码所示。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCViewDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public ActionResult Index(){
         return View();
      }
		
      public string Mycontroller(){
         return "Hi, I am a controller";
      }
   }
}

第 9 步– 运行此应用程序并将 /Home/MyController 附加到浏览器中的 URL,然后按 Enter。您将收到以下输出。

我的控制器

由于 MyController 操作只是返回字符串,要从操作返回一个视图,我们需要先添加一个视图。

第 10 步– 在添加视图之前,让我们添加另一个操作,它将返回默认视图。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCViewDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public ActionResult Index(){
         return View();
      }
		
      public string Mycontroller(){
         return "Hi, I am a controller";
      }
		
      public ActionResult MyView(){
         return View();
      }
   }
}

步骤 11 – 运行此应用程序并将 /Home/MyView 附加到浏览器中的 URL,然后按 Enter。您将收到以下输出。

我的视图

你可以在这里看到我们有一个错误,这个错误实际上是非常具有描述性的,它告诉我们它找不到 MyView 视图。

步骤 12 – 要添加视图,请在 MyView 操作内右键单击并选择添加视图。

我的视图操作

它将显示“添加视图”对话框,并将添加默认名称。

添加视图对话框

步骤 13 – 取消选中“使用布局页面”复选框,然后单击“添加”按钮。

我们现在在视图中有默认代码。

使用布局页面

步骤 14 – 使用以下代码在此视图中添加一些文本。

@{
   Layout = null;
}

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>MyView</title>
   </head>
	
   <body>
      <div>
         Hi, I am a view
      </div>
   </body>
	
</html>

第 15 步– 运行此应用程序并将 /Home/MyView 附加到浏览器中的 URL。按回车键,您将收到以下输出。

我是视图

您现在可以从视图中看到文本。

ASP.NET MVC – 数据模型

在本章中,我们将讨论在 ASP.NET MVC 框架应用程序中构建模型。模型存储被根据来自控制器的命令检索并在视图中显示的数据。

模型是一组类,您将在其中处理数据和业务逻辑。因此,基本上模型是特定于业务领域的容器。它用于与数据库交互。它还可以用于操作数据以实现业务逻辑。

让我们通过创建一个新的 ASP.Net MVC 项目来看看 Model 的一个简单示例。

步骤 1 – 打开 Visual Studio。单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

打开视觉工作室

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称“MVCSimpleApp”,然后单击确定继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVC简单应用程序

第 5 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。

它将创建一个具有最少预定义内容的基本 MVC 项目。

我们现在需要添加一个控制器。

步骤 6 – 右键单击​​解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

它将显示“添加脚手架”对话框。

右键单击控制器文件夹

步骤 7 – 选择 MVC 5 控制器 – 带有读/写操作选项。此模板将为 Controller 创建一个具有默认操作的 Index 方法。这还将列出其他方法,如编辑/删除/创建。

步骤 8 – 单击“添加”按钮,将出现“添加控制器”对话框。

添加员工控制器

第 9 步– 将名称设置为 EmployeeController 并单击“添加”按钮。

第 10 步– 您将在 Controllers 文件夹中看到一个新的 C# 文件“EmployeeController.cs”,该文件在 Visual Studio 中打开以使用一些默认操作进行编辑。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCSimpleApp.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      public ActionResult Index(){
         return View();
      }
		
      // GET: Employee/Details/5
      public ActionResult Details(int id){
         return View();
      }
		
      // GET: Employee/Create
      public ActionResult Create(){
         return View();
      }
		
      // POST: Employee/Create
      [HttpPost]
      public ActionResult Create(FormCollection collection){
         try{
            // TODO: Add insert logic here
            return RedirectToAction("Index");
         }catch{
            return View();
         }
      }
		
      // GET: Employee/Edit/5
      public ActionResult Edit(int id){
         return View();
      }
		
      // POST: Employee/Edit/5
      [HttpPost]
      public ActionResult Edit(int id, FormCollection collection){
         try{
            // TODO: Add update logic here
            return RedirectToAction("Index");
         }catch{
            return View();
         }
      }
		
      // GET: Employee/Delete/5
      public ActionResult Delete(int id){
         return View();
      }
		
      // POST: Employee/Delete/5
      [HttpPost]
      public ActionResult Delete(int id, FormCollection collection){
         try{
            // TODO: Add delete logic here
            return RedirectToAction("Index");
         }catch{
            return View();
         }
      }
   }
}

让我们添加一个模型。

步骤 11 – 右键单击​​解决方案资源管理器中的模型文件夹,然后选择添加 → 类。

右键单击模型文件夹

您将看到“添加新项目”对话框。

添加新项目对话框

步骤 12 – 在中间盘中选择 Class 并在 name 字段中输入 Employee.cs。

步骤 13 – 使用以下代码向 Employee 类添加一些属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCSimpleApp.Models {
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
}

让我们通过添加另一个方法来更新 EmployeeController.cs 文件,该方法将返回员工列表。

[NonAction]
public List<Employee> GetEmployeeList(){
   return new List<Employee>{
      new Employee{
         ID = 1,
         Name = "Allan",
         JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
         Age = 23
      },
		
      new Employee{
         ID = 2,
         Name = "Carson",
         JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
         Age = 45
      },
		
      new Employee{
         ID = 3,
         Name = "Carson",
         JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
         Age = 37
      },
		
      new Employee{
         ID = 4,
         Name = "Laura",
         JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
         Age = 26
      },
   };
}

步骤 14 – 更新索引操作方法,如下面的代码所示。

public ActionResult Index(){
   var employees = from e in GetEmployeeList()
   orderby e.ID
   select e;
   return View(employees);
}

第 15 步– 运行此应用程序并将 /employee 附加到浏览器中的 URL,然后按 Enter。您将看到以下输出。

找不到索引视图

如上面的截图所示,有一个错误,这个错误实际上是非常具有描述性的,它告诉我们它找不到索引视图。

步骤 16 – 因此,要添加视图,请在“索引”操作内右键单击并选择“添加视图”。

右键单击索引操作

它将显示“添加视图”对话框,并将添加默认名称。

添加默认名称

步骤 17 – 从模板下拉列表和模型类下拉列表中的员工中选择列表,并取消选中“使用布局页面”复选框并单击“添加”按钮。

它将在此视图中为您添加一些默认代码。

@model IEnumerable<MVCSimpleApp.Models.Employee>
@{
   Layout = null;
}

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Index</title>
   </head>
	
   <body>
      <p>@Html.ActionLink("Create New", "Create")</p>
         <table class = "table">
         <tr>
            <th>
               @Html.DisplayNameFor(model => model.Name)
            </th>
				
            <th>
               @Html.DisplayNameFor(model => model.JoiningDate)
            </th>
				
            <th>
               @Html.DisplayNameFor(model => model.Age)
            </th>
				
            <th></th>
         </tr>
			
         @foreach (var item in Model) {
            <tr>
               <td>
                  @Html.DisplayFor(modelItem => item.Name)
               </td>
					
               <td>
                  @Html.DisplayFor(modelItem => item.JoiningDate)
               </td>
					
               <td>
                  @Html.DisplayFor(modelItem => item.Age)
               </td>
					
               <td>
                  @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                  @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                  @Html.ActionLink("Delete", "Delete", new { id = item.ID })
               </td>
					
            </tr>
         }
			
      </table>
   </body>
</html>

步骤 18 – 运行此应用程序,您将收到以下输出。

员工名单

将显示员工列表。

ASP.NET MVC – 助手

在 ASP.Net Web 表单中,开发人员使用工具箱在任何特定页面上添加控件。但是,在 ASP.NET MVC 应用程序中,没有可用于在视图上拖放 HTML 控件的工具箱。在 ASP.NET MVC 应用程序中,如果你想创建一个视图,它应该包含 HTML 代码。所以那些刚接触 MVC 的开发人员,尤其是具有 Web 表单背景的开发人员会发现这有点困难。

为了克服这个问题,ASP.NET MVC 提供了 HtmlHelper 类,其中包含帮助您以编程方式创建 HTML 控件的不同方法。所有 HtmlHelper 方法都会生成 HTML 并将结果作为字符串返回。最终的 HTML 是由这些函数在运行时生成的。HtmlHelper 类旨在生成 UI,不应在控制器或模型中使用它。

有不同类型的辅助方法。

  • Createinputs – 创建文本框和按钮的输入。

  • Createlinks – 创建基于路由表信息的链接。

  • Createforms – 创建可以回发到我们的动作的表单标签,或者回发到不同控制器上的动作。

Sr.No. 方法和说明
1

Action(String)

超载。调用指定的子操作方法并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

2

Action(String, Object)

超载。使用指定的参数调用指定的子操作方法,并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

3

Action(String, RouteValueDictionary)

超载。使用指定的参数调用指定的子操作方法并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

4

Action(String, String)

超载。使用指定的控制器名称调用指定的子操作方法,并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

5

Action(String, String, Object)

超载。使用指定的参数和控制器名称调用指定的子操作方法,并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

6

Action(String, String, RouteValueDictionary)

超载。使用指定的参数和控制器名称调用指定的子操作方法,并将结果作为 HTML 字符串返回。(由 ChildActionExtensions 定义)

7

ActionLink(String, String)

超载。(由 LinkExtensions 定义)

8

ActionLink(String, String, Object)

超载。(由 LinkExtensions 定义)

9

ActionLink(String, String, Object, Object)

超载。(由 LinkExtensions 定义)

10

ActionLink(String, String, RouteValueDictionary)

超载。(由 LinkExtensions 定义)

11

ActionLink(String, String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

12

ActionLink(String, String, String)

超载。(由 LinkExtensions 定义)

13

ActionLink(String, String, String, Object, Object)

超载。(由 LinkExtensions 定义)

14

ActionLink(String, String, String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

15

ActionLink(String, String, String, String, String, String, Object, Object)

超载。(由 LinkExtensions 定义)

16

ActionLink(String, String, String, String, String, String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

17

BeginForm()

超载。将一个开始的 <form> 标记写入响应。表单使用POST方法,请求由视图的action方法处理。(由 FormExtensions 定义)

18

BeginForm(Object)

超载。将一个开始的 <form> 标记写入响应,并在 action 属性中包含路由值。表单使用POST方法,请求由视图的action方法处理。(由 FormExtensions 定义)

19

BeginForm(RouteValueDictionary)

超载。将开始 <form> 标记写入响应,并在 action 属性中包含路由值字典中的路由值。表单使用POST方法,请求由视图的action方法处理。(由 FormExtensions 定义。)

20

BeginForm(String, String)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器和操作。该表单使用 POST 方法。(由 FormExtensions 定义)

21

BeginForm(String, String, FormMethod)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器和操作。该表单使用指定的 HTTP 方法。(由 FormExtensions 定义)

22

BeginForm(String, String, FormMethod, IDictionary<String, Object>)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器和操作。该表单使用指定的 HTTP 方法并包含字典中的 HTML 属性。(由 FormExtensions 定义)

23

BeginForm(String, String, FormMethod, Object)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器和操作。该表单使用指定的 HTTP 方法并包含 HTML 属性。(由 FormExtensions 定义)

24

BeginForm(String, String, Object)

超载。将开始的 <form> 标记写入响应,并将操作标记设置为指定的控制器、操作和路由值。该表单使用 POST 方法。(由 FormExtensions 定义)

25

BeginForm(String, String, Object, FormMethod)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器、操作和路由值。该表单使用指定的 HTTP 方法。(由 FormExtensions 定义)

26

BeginForm(String, String, Object, FormMethod, Object)

超载。将开始的 <form> 标记写入响应并将操作标记设置为指定的控制器、操作和路由值。该表单使用指定的 HTTP 方法并包含 HTML 属性。(由 FormExtensions 定义)

27

BeginForm(String, String, RouteValueDictionary)

超载。将开始的 <form> 标记写入响应,并将操作标记设置为路由值字典中指定的控制器、操作和路由值。该表单使用 POST 方法。(由 FormExtensions 定义)

28

BeginForm(String, String, RouteValueDictionary, FormMethod)

超载。将开始的 <form> 标记写入响应,并将操作标记设置为路由值字典中指定的控制器、操作和路由值。该表单使用指定的 HTTP 方法。(由 FormExtensions 定义)

29

BeginForm(String, String, RouteValueDictionary, FormMethod, IDictionary<String, Object>)

超载。将开始的 <form> 标记写入响应,并将操作标记设置为路由值字典中指定的控制器、操作和路由值。该表单使用指定的 HTTP 方法,并包含字典中的 HTML 属性。(由 FormExtensions 定义)

30

BeginRouteForm(Object)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

31

BeginRouteForm(RouteValueDictionary)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

32

BeginRouteForm(String)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

33

BeginRouteForm(String, FormMethod)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

34

BeginRouteForm(String, FormMethod, IDictionary<String, Object>)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

35

BeginRouteForm(String, FormMethod, Object)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

36

BeginRouteForm(String, Object)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

37

BeginRouteForm(String, Object, FormMethod)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

38

BeginRouteForm(String, Object, FormMethod, Object)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

39

BeginRouteForm(String, RouteValueDictionary)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

40

BeginRouteForm(String, RouteValueDictionary, FormMethod)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

41

BeginRouteForm(String, RouteValueDictionary, FormMethod, IDictionary<String, Object>)

超载。将一个开始的 <form> 标记写入响应。当用户提交表单时,请求将由路由目标处理。(由 FormExtensions 定义)

42

CheckBox(String)

超载。使用指定的 HTML 帮助程序和表单字段的名称返回复选框输入元素。(由 InputExtensions 定义)

43

CheckBox(String, Boolean)

超载。通过使用指定的 HTML 帮助程序、表单字段的名称和指示复选框是否被选中的值,返回复选框输入元素。(由 InputExtensions 定义)

44

CheckBox(String, Boolean, IDictionary<String, Object>)

超载。通过使用指定的 HTML 帮助程序、表单字段的名称、指示是否选中复选框的值以及 HTML 属性返回复选框输入元素。(由 InputExtensions 定义)

45

CheckBox(String, Boolean, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指示是否选中复选框的值以及 HTML 属性返回复选框输入元素。(由 InputExtensions 定义)

46

CheckBox(String, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称和 HTML 属性返回复选框输入元素。(由 InputExtensions 定义)

47

CheckBox(String, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称和 HTML 属性返回复选框输入元素。(由 InputExtensions 定义)

48

Display(String)

超载。为由字符串表达式表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

49

Display(String, Object)

超载。使用附加的视图数据为由字符串表达式表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

50

Display(String, String)

超载。使用指定的模板为表达式所表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

51

Display(String, String, Object)

超载。使用指定的模板和附加视图数据,为表达式所表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

52

Display(String, String, String)

超载。使用指定的模板和 HTML 字段 ID,为表达式所表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

53

Display(String, String, String, Object)

超载。使用指定的模板、HTML 字段 ID 和附加视图数据,为表达式所表示的对象中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

54

DisplayForModel()

超载。返回模型中每个属性的 HTML 标记。(由 DisplayExtensions 定义)

55

DisplayForModel(Object)

超载。使用额外的视图数据为模型中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

56

DisplayForModel(String)

超载。使用指定的模板为模型中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

57

DisplayForModel(String, Object)

超载。使用指定的模板和附加视图数据为模型中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

58

DisplayForModel(String, String)

超载。使用指定的模板和 HTML 字段 ID 为模型中的每个属性返回 HTML 标记。(由 DisplayExtensions 定义)

59

DisplayForModel(String, String, Object)

超载。使用指定的模板、HTML 字段 ID 和其他视图数据返回模型中每个属性的 HTML 标记。(由 DisplayExtensions 定义)

60

DisplayName(String)

获取显示名称。(由 DisplayNameExtensions 定义)

61

DisplayNameForModel()

获取模型的显示名称。(由 DisplayNameExtensions 定义)

62

DisplayText(String)

为由指定表达式表示的对象中的每个属性返回 HTML 标记。(由 DisplayTextExtensions 定义)

63

DropDownList(String)

超载。使用指定的 HTML 帮助器和表单字段的名称返回单选 select 元素。(由 SelectExtensions 定义)

64

DropDownList(String, IEnumerable<SelectListItem>)

超载。使用指定的 HTML 帮助程序、表单字段的名称和指定的列表项返回单选 select 元素。(由 SelectExtensions 定义)

65

DropDownList(String, IEnumerable<SelectListItem>, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项和指定的 HTML 属性返回单选 select 元素。(由 SelectExtensions 定义)

66

DropDownList(String, IEnumerable<SelectListItem>, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项和指定的 HTML 属性返回单选 select 元素。(由 SelectExtensions 定义)

67

DropDownList(String, IEnumerable<SelectListItem>, String)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项和选项标签返回单选 select 元素。(由 SelectExtensions 定义)

68

DropDownList(String, IEnumerable<SelectListItem>, String, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项、选项标签和指定的 HTML 属性返回单选 select 元素。(由 SelectExtensions 定义)

69

DropDownList(String, IEnumerable<SelectListItem>, String, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项、选项标签和指定的 HTML 属性返回单选 select 元素。(由 SelectExtensions 定义)

70

DropDownList(String, String)

超载。使用指定的 HTML 帮助程序、表单字段的名称和选项标签返回单选 select 元素。(由 SelectExtensions 定义)

71

Editor(String)

超载。为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

72

Editor(String, Object)

超载。使用附加的视图数据,为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

73

Editor(String, String)

超载。使用指定的模板,为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

74

Editor(String, String, Object)

超载。使用指定的模板和附加视图数据,为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

75

Editor(String, String, String)

超载。使用指定的模板和 HTML 字段名称,为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

76

Editor(String, String, String, Object)

超载。使用指定的模板、HTML 字段名称和附加视图数据,为表达式所表示的对象中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

77

EditorForModel()

超载。为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

78

EditorForModel(Object)

超载。使用额外的视图数据为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

79

EditorForModel(String)

超载。使用指定的模板为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

80

EditorForModel(String, Object)

超载。使用指定的模板和附加视图数据为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

81

EditorForModel(String, String)

超载。使用指定的模板名称和 HTML 字段名称为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

82

EditorForModel(String, String, Object)

超载。使用模板名称、HTML 字段名称和附加视图数据为模型中的每个属性返回一个 HTML 输入元素。(由 EditorExtensions 定义)

83

EndForm()

将结束 </form> 标记呈现给响应。(由 FormExtensions 定义)

84

Hidden(String)

超载。使用指定的 HTML 帮助程序和表单字段的名称返回隐藏的输入元素。(由 InputExtensions 定义)

85

Hidden(String, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称和值返回隐藏的输入元素。(由 InputExtensions 定义)

86

Hidden(String, Object, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回隐藏的 input 元素。(由 InputExtensions 定义)

87

Hidden(String, Object, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回隐藏的 input 元素。(由 InputExtensions 定义)

88

Id(String)

获取 HtmlHelper 字符串的 ID。(由 NameExtensions 定义)

89

IdForModel()

获取 HtmlHelper 字符串的 ID。(由 NameExtensions 定义)

90

Label(String)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

91

Label(String, IDictionary<String, Object>)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

92

Label(String, Object)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

93

Label(String, String)

超载。返回一个 HTML 标签元素以及由使用标签文本的指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

94

Label(String, String, IDictionary<String, Object>)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

95

Label(String, String, Object)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

96

LabelForModel()

超载。返回一个 HTML 标签元素和模型表示的属性的属性名称。(由 LabelExtensions 定义)

97

LabelForModel(IDictionary<String, Object>)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

98

LabelForModel(Object)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

99

LabelForModel(String)

超载。返回一个 HTML 标签元素以及由使用标签文本的指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

100

LabelForModel(String, IDictionary<String, Object>)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

101

LabelForModel(String, Object)

超载。返回一个 HTML 标签元素和由指定表达式表示的属性的属性名称。(由 LabelExtensions 定义)

102

ListBox(String)

超载。使用指定的 HTML 帮助程序和表单字段的名称返回多选 select 元素。(由 SelectExtensions 定义)

103

ListBox(String, IEnumerable<SelectListItem>)

超载。使用指定的 HTML 帮助器、表单字段的名称和指定的列表项返回多选 select 元素。(由 SelectExtensions 定义)

104

ListBox(String, IEnumerable<SelectListItem>, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、指定的列表项和指定的 HMTL 属性返回多选 select 元素。(由 SelectExtensions 定义)

105

ListBox(String, IEnumerable<SelectListItem>, Object)

超载。使用指定的 HTML 帮助器、表单字段的名称和指定的列表项返回多选 select 元素。(由 SelectExtensions 定义)

106

Name(String)

获取由表达式表示的对象的完整 HTML 字段名称。(由 NameExtensions 定义)

107

NameForModel()

获取由表达式表示的对象的完整 HTML 字段名称。(由 NameExtensions 定义。)

108

Partial(String)

超载。将指定的局部视图呈现为 HTMLencoded 字符串。(由 PartialExtensions 定义)

109

Partial(String, Object)

超载。将指定的局部视图呈现为 HTMLencoded 字符串。(由 PartialExtensions 定义)

110

Partial(String, Object, ViewDataDictionary)

超载。将指定的局部视图呈现为 HTMLencoded 字符串。(由 PartialExtensions 定义)

111

Partial(String, ViewDataDictionary)

超载。将指定的局部视图呈现为 HTMLencoded 字符串。(由 PartialExtensions 定义)

112

Password(String)

超载。使用指定的 HTML 帮助程序和表单字段的名称返回密码输入元素。(由 InputExtensions 定义)

113

Password(String, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称和值返回密码输入元素。(由 InputExtensions 定义)

114

Password(String, Object, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回密码输入元素。(由 InputExtensions 定义)

115

Password(String, Object, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回密码输入元素。(由 InputExtensions 定义)

116

RadioButton(String, Object)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

117

RadioButton(String, Object, Boolean)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

118

RadioButton(String, Object, Boolean, IDictionary<String, Object>)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

119

RadioButton(String, Object, Boolean, Object)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

120

RadioButton(String, Object, IDictionary<String, Object>)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

121

RadioButton(String, Object, Object)

超载。返回用于呈现互斥选项的单选按钮输入元素。(由 InputExtensions 定义)

122

RenderAction(String)

超载。调用指定的子操作方法并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

123

RenderAction(String, Object)

超载。使用指定的参数调用指定的子操作方法,并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

124

RenderAction(String, RouteValueDictionary)

超载。使用指定的参数调用指定的子操作方法,并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

125

RenderAction(String, String)

超载。使用指定的控制器名称调用指定的子操作方法,并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

126

RenderAction(String, String, Object)

超载。使用指定的参数和控制器名称调用指定的子操作方法,并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

127

RenderAction(String, String, RouteValueDictionary)

超载。使用指定的参数和控制器名称调用指定的子操作方法,并在父视图中内联呈现结果。(由 ChildActionExtensions 定义)

128

RenderPartial(String)

超载。使用指定的 HTML 帮助程序呈现指定的局部视图。(由 RenderPartialExtensions 定义)

129

RenderPartial(String, Object)

超载。呈现指定的局部视图,将当前 ViewDataDictionary 对象的副本传递给它,但将 Model 属性设置为指定的模型。(由 RenderPartialExtensions 定义)

130

RenderPartial(String, Object, ViewDataDictionary)

超载。呈现指定的局部视图,将局部视图的 ViewData 属性替换为指定的 ViewDataDictionary 对象,并将视图数据的 Model 属性设置为指定的模型。(由 RenderPartialExtensions 定义)

131

RenderPartial(String, ViewDataDictionary)

超载。呈现指定的局部视图,用指定的 ViewDataDictionary 对象替换其 ViewData 属性。(由 RenderPartialExtensions 定义)

132

RouteLink(String, Object)

超载。(由 LinkExtensions 定义)

133

RouteLink(String, Object, Object)

超载。(由 LinkExtensions 定义)

134

RouteLink(String, RouteValueDictionary)

超载。(由 LinkExtensions 定义)

135

RouteLink(String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

136

RouteLink(String, String)

超载。(由 LinkExtensions 定义)

137

RouteLink(String, String, Object)

超载。(由 LinkExtensions 定义)

138

RouteLink(String, String, Object, Object)

超载。(由 LinkExtensions 定义)

139

RouteLink(String, String, RouteValueDictionary)

超载。(由 LinkExtensions 定义)

140

RouteLink(String, String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

141

RouteLink(String, String, String, String, String, Object, Object)

超载。(由 LinkExtensions 定义)

142

RouteLink(String, String, String, String, String, RouteValueDictionary, IDictionary<String, Object>)

超载。(由 LinkExtensions 定义)

143

TextArea(String)

超载。使用指定的 HTML 帮助器和表单字段的名称返回指定的 textarea 元素。(由 TextAreaExtensions 定义。)

144

TextArea(String, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助器、表单字段的名称和指定的 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

145

TextArea(String, Object)

超载。使用指定的 HTML 帮助程序和 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

146

TextArea(String, String)

超载。使用指定的 HTML 帮助器、表单字段的名称和文本内容返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

147

TextArea(String, String, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助器、表单字段的名称、文本内容和指定的 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

148

TextArea(String, String, Int32, Int32, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助器、表单字段的名称、文本内容、行数和列数以及指定的 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

149

TextArea(String, String, Int32, Int32, Object)

超载。使用指定的 HTML 帮助器、表单字段的名称、文本内容、行数和列数以及指定的 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

150

TextArea(String, String, Object)

超载。使用指定的 HTML 帮助器、表单字段的名称、文本内容和指定的 HTML 属性返回指定的 textarea 元素。(由 TextAreaExtensions 定义)

151

TextBox(String)

超载。使用指定的 HTML 帮助程序和表单字段的名称返回文本输入元素。(由 InputExtensions 定义)

152

TextBox(String, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称和值返回文本输入元素。(由 InputExtensions 定义)

153

TextBox(String, Object, IDictionary<String, Object>)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回文本输入元素。(由 InputExtensions 定义)

154

TextBox(String, Object, Object)

超载。使用指定的 HTML 帮助程序、表单字段的名称、值和 HTML 属性返回文本输入元素。(由 InputExtensions 定义)

155

TextBox(String, Object, String)

超载。返回一个文本输入元素。(由 InputExtensions 定义)

156

TextBox(String, Object, String, IDictionary<String, Object>)

超载。返回一个文本输入元素。(由 InputExtensions 定义)

157

TextBox(String, Object, String, Object)

超载。返回一个文本输入元素。(由 InputExtensions 定义)

158

Validate(String)

检索指定模型的验证元数据并将每个规则应用于数据字段。(由 ValidationExtensions 定义)

159

ValidationMessage(String)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义)

160

ValidationMessage(String, IDictionary<String, Object>)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义。)

161

ValidationMessage(String, IDictionary<String, Object>, String)

超载。如果 ModelStateDictionary 对象中的指定条目存在错误,则显示验证消息。(由 ValidationExtensions 定义)

162

ValidationMessage(String, Object)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义)

163

ValidationMessage(String, Object, String)

超载。如果 ModelStateDictionary 对象中的指定条目存在错误,则显示验证消息。(由 ValidationExtensions 定义)

164

ValidationMessage(String, String)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义)

165

ValidationMessage(String, String, IDictionary<String, Object>)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义)

166

ValidationMessage(String, String, IDictionary<String, Object>, String)

超载。如果 ModelStateDictionary 对象中的指定条目存在错误,则显示验证消息。(由 ValidationExtensions 定义)

167

ValidationMessage(String, String, Object)

超载。如果 ModelStateDictionary 对象中的指定字段存在错误,则显示验证消息。(由 ValidationExtensions 定义)

168

ValidationMessage(String, String, Object, String)

超载。如果 ModelStateDictionary 对象中的指定条目存在错误,则显示验证消息。(由 ValidationExtensions 定义)

169

ValidationMessage(String, String, String)

超载。如果 ModelStateDictionary 对象中的指定条目存在错误,则显示验证消息。(由 ValidationExtensions 定义)

170

ValidationSummary()

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素)。(由 ValidationExtensions 定义)

171

ValidationSummary(Boolean)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素),并可选择仅显示模型级错误。(由 ValidationExtensions 定义)

172

ValidationSummary(Boolean, String)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素),并可选择仅显示模型级错误。(由 ValidationExtensions 定义)

173

ValidationSummary(Boolean, String, IDictionary<String, Object>)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素),并可选择仅显示模型级错误。(由 ValidationExtensions 定义)

174

ValidationSummary(Boolean, String, IDictionary<String, Object>, String)

超载。(由 ValidationExtensions 定义)

175

ValidationSummary(Boolean, String, Object)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素),并可选择仅显示模型级错误。(由 ValidationExtensions 定义)

176

ValidationSummary(Boolean, String, Object, String)

超载。(由 ValidationExtensions 定义)

177

ValidationSummary(Boolean, String, String)

超载。(由 ValidationExtensions 定义)

178

ValidationSummary(String)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素)。(由 ValidationExtensions 定义)

179

ValidationSummary(String, IDictionary<String, Object>)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素)。(由 ValidationExtensions 定义)

180

ValidationSummary(String, IDictionary<String, Object>, String)

超载。(由 ValidationExtensions 定义)

181

ValidationSummary(String, Object)

超载。返回 ModelStateDictionary 对象中验证消息的无序列表(ul 元素)。(由 ValidationExtensions 定义)

182

ValidationSummary(String, Object, String)

超载。(由 ValidationExtensions 定义)

183

ValidationSummary(String, String)

超载。(由 ValidationExtensions 定义)

184

Value(String)

超载。提供一种机制来创建与 ASP.NET MVC 模型绑定器和模板兼容的自定义 HTML 标记。(由 ValueExtensions 定义)

185

Value(String, String)

超载。提供一种机制来创建与 ASP.NET MVC 模型绑定器和模板兼容的自定义 HTML 标记。(由 ValueExtensions 定义)

186

ValueForModel()

超载。提供一种机制来创建与 ASP.NET MVC 模型绑定器和模板兼容的自定义 HTML 标记。(由 ValueExtensions 定义)

187

ValueForModel(String)

超载。提供一种机制来创建与 ASP.NET MVC 模型绑定器和模板兼容的自定义 HTML 标记。(由 ValueExtensions 定义)

如果您查看我们从 EmployeeController 索引操作生成的上一章的视图,您将看到以 Html 开头的操作数量,例如Html.ActionLinkHtml.DisplayNameFor等,如下面的代码所示。

@model IEnumerable<MVCSimpleApp.Models.Employee>
@{
   Layout = null;
} 

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Index</title>
   </head>
	
   <body>
      <p>
         @Html.ActionLink("Create New", "Create")
      </p>
		
      <table class = "table">
         <tr>
            <th>
               @Html.DisplayNameFor(model => model.Name)
            </th>
				
            <th>
               @Html.DisplayNameFor(model => model.JoiningDate)
            </th>
				
            <th>
               @Html.DisplayNameFor(model => model.Age)
            </th>
				
            <th></th>
         </tr>
			
         @foreach (var item in Model) {
            <tr>
               <td>
                  @Html.DisplayFor(modelItem => item.Name)
               </td>
					
               <td>
                  @Html.DisplayFor(modelItem => item.JoiningDate)
               </td>
					
               <td>
                  @Html.DisplayFor(modelItem => item.Age)
               </td>
					
               <td>
                  @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                  @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                  @Html.ActionLink("Delete", "Delete", new { id = item.ID })
               </td>
            </tr>
         }
			
      </table>
   </body>
</html>

这个 HTML 是我们从 ViewPage 基类继承的一个属性。因此,它在我们所有的视图中都可用,并且它返回一个名为 HTML Helper 类型的实例。

让我们看一个简单的示例,在该示例中我们将使用户能够编辑员工。因此,此编辑操作将使用大量不同的 HTML 帮助程序。

如果你看上面的代码,你会在最后看到下面的 HTML Helper 方法

@Html.ActionLink("Edit", "Edit", new { id = item.ID })

在ActionLink helper中,第一个参数是链接的“Edit”,第二个参数是Controller中的action方法,也是“Edit”,第三个参数ID是您要编辑的任何特定员工.

让我们通过添加静态列表来更改 EmployeeController 类,并使用以下代码更改索引操作。

public static List<Employee> empList = new List<Employee>{
   new Employee{
      ID = 1,
      Name = "Allan",
      JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
      Age = 23
   },
	
   new Employee{
      ID = 2,
      Name = "Carson",
      JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
      Age = 45
   },
	
   new Employee{
      ID = 3,
      Name = "Carson",
      JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
      Age = 37
   },
	
   new Employee{
      ID = 4,
      Name = "Laura",
      JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
      Age = 26
   },
	
};

public ActionResult Index(){
   var employees = from e in empList
   orderby e.ID
   select e;
   return View(employees);
}

让我们更新编辑操作。您将看到两个 Edit 操作,一个用于GET,另一个用于POST让我们更新Get的 Edit 操作,它的参数中只有 Id,如以下代码所示。

// GET: Employee/Edit/5
public ActionResult Edit(int id){
   List<Employee> empList = GetEmployeeList();
   var employee = empList.Single(m => m.ID == id);
   return View(employee);
}

现在,我们知道我们有 Edit 操作,但我们没有这些操作的任何视图。所以我们还需要添加一个视图。为此,请右键单击“编辑”操作并选择“添加视图”。

右键单击编辑操作

您将看到视图的默认名称。从模板下拉列表中选择编辑,从模型类下拉列表中选择员工。

以下是编辑视图中的默认实现。

@model MVCSimpleApp.Models.Employee
@{
   Layout = null;
}

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Edit</title>
   </head>
	
   <body>
      @using (Html.BeginForm()){
         @Html.AntiForgeryToken()
         <div class = "form-horizontal">
            <h4>Employee</h4>
            <hr />
            @Html.ValidationSummary(
               true, "", new { @class = "text-danger" })
					
            @Html.HiddenFor(model => model.ID)
				
            <div class = "form-group">
               @Html.LabelFor(
                  model => model.Name, htmlAttributes: new{
                     @class = "control-label col-md-2" })
							
               <div class = "col-md-10">
                  @Html.EditorFor(model => model.Name, new{
                     htmlAttributes = new {
                        @class = "form-control" } })
								
                  @Html.ValidationMessageFor(model => model.Name, "", new{
                        @class = "text-danger" })
               </div>
					
            </div>
				
            <div class = "form-group">
               @Html.LabelFor(
                  model => model.JoiningDate, htmlAttributes: new{
                     @class = "control-label col-md-2" })
							
               <div class = "col-md-10">
                  @Html.EditorFor(
                     model => model.JoiningDate, new{
                        htmlAttributes = new{ @class = "form-control" } })
								
                  @Html.ValidationMessageFor(
                     model => model.JoiningDate, "", new{
                        @class = "text-danger" })
               </div>
					
            </div>
				
            <div class = "form-group">
               @Html.LabelFor(
                  model => model.Age, htmlAttributes: new{
                     @class = "control-label col-md-2" })
							
               <div class = "col-md-10">
                  @Html.EditorFor(
                     model => model.Age, new{
                        htmlAttributes = new{ @class = "form-control" } })
								
                  @Html.ValidationMessageFor(
                     model => model.Age, "", new{
                        @class = "text-danger" })
               </div>
					
            </div>
				
            <div class = "form-group">
               <div class = "col-md-offset-2 col-md-10">
                  <input type = "submit" value = "Save" class = "btn btn-default"/>
               </div>
            </div>
				
         </div>
      }
		
      <div>
         @Html.ActionLink("Back to List", "Index")
      </div>
		
   </body>
</html>

如您所见,使用了许多辅助方法。所以,这里“HTML.BeginForm”写了一个打开的表单标签。它还确保当用户单击“保存”按钮时该方法将是“发布”。

Html.BeginForm 非常有用,因为它使您可以更改 URL、更改方法等。

在上面的代码中,您将看到另一个 HTML 助手,即“@HTML.HiddenFor”,它发出隐藏字段。

MVC 框架足够聪明,可以确定模型类中提到了这个 ID 字段,因此需要防止它被编辑,这就是它被标记为隐藏的原因。

Html.LabelFor HTML Helper 在屏幕上创建标签。如果在进行更改时输入错误,则 Html.ValidationMessageFor 助手会显示正确的错误消息。

我们还需要更改 POST 的 Edit 操作,因为一旦您更新员工,它将调用此操作。

// POST: Employee/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection){
   try{
      var employee = empList.Single(m => m.ID == id);
      if (TryUpdateModel(employee)){
         //To Do:- database code
         return RedirectToAction("Index");
      }
      return View(employee);
   }catch{
      return View();
   }
}

让我们运行这个应用程序并请求以下 URL http://localhost:63004/employee您将收到以下输出。

本地员工

单击任何特定员工的编辑链接,假设单击 Allan 编辑链接。您将看到以下视图。

单击特定员工

让我们将年龄从 23 更改为 29 并单击“保存”按钮,然后您将在索引视图中看到更新的年龄。

更新的年龄索引视图

ASP.NET MVC – 模型绑定

ASP.NET MVC 模型绑定允许您使用模型映射 HTTP 请求数据。它是使用浏览器在 HTTP 请求中发送的数据创建 .NET 对象的过程。刚接触 ASP.Net MVC 的 ASP.NET Web Forms 开发人员最困惑的是,当 View 的值到达 Controller 类的 Action 方法时,它是如何转换为 Model 类的,因此这种转换是由 Model binder 完成的。

模型绑定是 HTTP 请求和 C# 操作方法之间精心设计的桥梁。它使开发人员可以轻松地处理表单(视图)上的数据,因为 POST 和 GET 会自动传输到您指定的数据模型中。ASP.NET MVC 使用默认绑定器在幕后完成此操作。

让我们看一个简单的例子,我们在上一章的项目中添加了一个“创建视图”,我们将看到如何从视图中获取这些值到 EmployeeController 操作方法。

以下是 POST 的 Create Action 方法。

// POST: Employee/Create
[HttpPost]
public ActionResult Create(FormCollection collection){
   try{
      // TODO: Add insert logic here
      return RedirectToAction("Index");
   }catch{
      return View();
   }
}

右键单击 Create Action 方法并选择 Add View…

右键单击创建操作

它将显示添加视图对话框。

显示添加视图对话框

正如您在上面的屏幕截图中看到的,已经提到了默认名称。现在从模板下拉列表中选择创建,从模型类下拉列表中选择员工。

您将在 Create.cshtml 视图中看到默认代码。

@model MVCSimpleApp.Models.Employee
@{
   Layout = null;
}

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Create</title>
   </head>
	
   <body>
      @using (Html.BeginForm()){
         @Html.AntiForgeryToken()
         <div class = "form-horizontal">
            <h4>Employee</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
				
            <div class = "form-group">
               @Html.LabelFor(model => model.Name, htmlAttributes:
                  new{ @class = "control-label col-md-2" })
						
               <div class = "col-md-10">
                  @Html.EditorFor(model => model.Name, new{ htmlAttributes =
                     new { @class = "form-control" } })
							
                  @Html.ValidationMessageFor(model => model.Name, "",
                     new{ @class = "text-danger" })
               </div>
            </div>
				
            <div class = "form-group">
               @Html.LabelFor(model => model.JoiningDate, htmlAttributes:
                  new{ @class = "control-label col-md-2" })
						
               <div class = "col-md-10">
                  @Html.EditorFor(model => model.JoiningDate, new{ htmlAttributes =
                     new { @class = "form-control" } })
							
                  @Html.ValidationMessageFor(model => model.JoiningDate, "",
                     new { @class = "text-danger" })
               </div>
            </div>
				
            <div class = "form-group">
               @Html.LabelFor(model => model.Age, htmlAttributes:
                  new { @class = "control-label col-md-2" })
						
               <div class = "col-md-10">
                  @Html.EditorFor(model => model.Age, new { htmlAttributes =
                     new { @class = "form-control" } })
							
                  @Html.ValidationMessageFor(model => model.Age, "", new{ @class = "text-danger" })
               </div>
            </div>
				
            <div class = "form-group">
               <div class = "col-md-offset-2 col-md-10">
                  <input type = "submit" value = "Create" class = "btn btn-default"/>
               </div>
            </div>
				
         </div>
      }
		
      <div>
         @Html.ActionLink("Back to List", "Index")
      </div>
		
   </body>
</html>

当用户在 Create View 上输入值时,它在 FormCollection 和 Request.Form 中可用。我们可以使用这些值中的任何一个来填充视图中的员工信息。

让我们使用以下代码通过 FormCollection 创建 Employee。

// POST: Employee/Create
[HttpPost]
public ActionResult Create(FormCollection collection){
   try {
      Employee emp = new Employee();
      emp.Name = collection["Name"];
      DateTime jDate;
      DateTime.TryParse(collection["DOB"], out jDate);
      emp.JoiningDate = jDate;
      string age = collection["Age"];
      emp.Age = Int32.Parse(age);
      empList.Add(emp);
      return RedirectToAction("Index");
   }catch {
      return View();
   }
}

运行此应用程序并请求此 URL http://localhost:63004/Employee/。您将收到以下输出。

本地主机员工输出

单击页面顶部的“新建”链接,它将转到以下视图。

创建新链接

让我们为您要添加的另一名员工输入数据。

另一个员工数据

单击创建按钮,您将看到新员工已添加到您的列表中。

添加了新员工

在上面的例子中,我们从 HTML 视图中获取所有发布的值,然后将这些值映射到 Employee 属性并一一分配它们。

在这种情况下,我们还将在发布的值与 Model 属性的格式不同的地方进行类型转换。

这也称为手动绑定,这种类型的实现对于简单和小数据模型可能不会那么糟糕。但是,如果您拥有庞大的数据模型并且需要大量类型转换,那么我们可以利用 ASP.NET MVC 模型绑定的强大功能和易用性。

让我们看一下我们为模型绑定所做的相同示例。

我们需要更改 Create Method 的参数以接受 Employee Model 对象而不是 FormCollection,如下面的代码所示。

// POST: Employee/Create
[HttpPost]
public ActionResult Create(Employee emp){
   try{
      empList.Add(emp);
      return RedirectToAction("Index");
   }catch{
      return View();
   }
}

现在模型绑定的魔力取决于提供值的 HTML 变量的 id。

对于我们的员工模型,HTML 输入字段的 id 应该与员工模型的属性名称相同,您可以看到 Visual Studio 在创建视图时使用模型的相同属性名称。

@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })

默认情况下,映射将基于属性名称。这是我们会发现 HTML 辅助方法非常有用的地方,因为这些辅助方法将生成 HTML,它将具有模型绑定工作的正确名称。

运行此应用程序并请求 URL http://localhost:63004/Employee/您将看到以下输出。

请求网址

让我们单击页面顶部的 Create New 链接,它将转到以下视图。

单击创建新链接

让我们输入要添加的另一名员工的数据。

输入数据另一名员工

现在单击创建按钮,您将看到使用 ASP.Net MVC 模型绑定将新员工添加到您的列表中。

MVC 模型绑定

ASP.NET MVC – 数据库

在本教程中创建的所有 ASP.NET MVC 应用程序中,我们一直将硬编码数据从控制器传递到视图模板。但是,为了构建真正的 Web 应用程序,您可能需要使用真正的数据库。在本章中,我们将看到如何使用数据库引擎来存储和检索应用程序所需的数据。

为了存储和检索数据,我们将使用称为实体框架的 .NET Framework 数据访问技术来定义和使用模型。

实体框架 (EF) 支持 Code First 技术,该技术允许您通过编写简单的类来创建模型对象,然后将从您的类动态创建数据库,从而实现非常干净和快速的开发工作流程。

让我们看一个简单的例子,我们将在我们的例子中添加对实体框架的支持。

第 1 步– 要安装实体框架,请右键单击您的项目并选择 NuGet 包管理器→管理解决方案的 NuGet 包…

安装实体框架

它将打开NuGet 包管理器在搜索框中搜索实体框架。

搜索实体框架

选择实体框架并单击“安装”按钮。它将打开“预览”对话框。

选择实体框架

单击确定继续。

许可接受

单击“我接受”按钮开始安装。

我接受按钮

安装实体框架后,您将在窗口中看到消息,如上面的屏幕截图所示。

添加数据库上下文

我们需要向 Employee 模型添加另一个类,该类将与实体框架通信以使用以下代码检索和保存数据。

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

using System.Web;

namespace MVCSimpleApp.Models{
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
	
   public class EmpDBContext : DbContext{
      public EmpDBContext()
      { }
      public DbSet<Employee> Employees { get; set; }
   }
}

如上所示,EmpDBContext派生自称为DbContext的 EF 类在这个类中,我们有一个名为 DbSet 的属性,它基本上代表您要查询和保存的实体。

连接字符串

我们需要在 <configuration> 标记下为 Web.config 文件中的数据库指定连接字符串。

<connectionStrings>
   <add name = "EmpDBContext" connectionString = "Data
   Source = (LocalDb)\v14.0;AttachDbFilename = |DataDirectory|\EmpDB.mdf;Initial
   Catalog = EmployeeDB;Integrated Security = SSPI;"
   providerName = "System.Data.SqlClient"/>
</connectionStrings>

您实际上不需要添加 EmpDBContext 连接字符串。如果不指定连接字符串,Entity Framework 将使用 DbContext 类的完全限定名称在用户目录中创建 localDB 数据库。对于这个演示,我们不会添加连接字符串来简化事情。

现在我们需要更新 EmployeeController.cs 文件,以便我们可以实际保存和检索数据库中的数据,而不是使用硬编码数据。

首先我们添加创建一个私有的 EmpDBContext 类对象,然后更新 Index、Create 和 Edit 操作方法,如下面的代码所示。

using MVCSimpleApp.Models;
using System.Linq;
using System.Web.Mvc;

namespace MVCSimpleApp.Controllers {
   public class EmployeeController : Controller{
      private EmpDBContext db = new EmpDBContext();
      // GET: Employee
		
      public ActionResult Index(){
         var employees = from e in db.Employees
         orderby e.ID
         select e;
         return View(employees);
      }
		
      // GET: Employee/Create
      public ActionResult Create(){
         return View();
      }
		
      // POST: Employee/Create
      [HttpPost]
      public ActionResult Create(Employee emp){
         try{
            db.Employees.Add(emp);
            db.SaveChanges();
            return RedirectToAction("Index");
         }catch{
            return View();
         }
      }
		
      // GET: Employee/Edit/5
      public ActionResult Edit(int id){
         var employee = db.Employees.Single(m => m.ID == id);
         return View(employee);
      }
		
      // POST: Employee/Edit/5
      [HttpPost]
      public ActionResult Edit(int id, FormCollection collection){
         try{
            var employee = db.Employees.Single(m => m.ID == id);
            if (TryUpdateModel(employee)){
               //To Do:- database code
               db.SaveChanges();
               return RedirectToAction("Index");
            }
            return View(employee);
         }catch{
            return View();
         }
      }
   }
}

然后我们使用以下 URL http://localhost:63004/Employee运行这个应用程序您将看到以下输出。

姓名 加入日期 年龄

如您所见,视图上没有数据,这是因为我们没有在我们的数据库中添加任何记录,这是由 Visual Studio 创建的。

让我们转到 SQL Server 对象资源管理器,您将看到创建的数据库与我们在 DBContext 类中的名称相同。

DBContext 类

让我们展开这个数据库,您将看到它有一个表,其中包含我们在 Employee 模型类中的所有字段。

员工模型类

要查看此表中的数据,请右键单击“雇员”表并选择“查看数据”。

员工表查看数据

您会看到我们目前没有任何记录。

无记录时刻

让我们直接在数据库中添加一些记录,如下面的屏幕截图所示。

在数据库中添加记录

刷新浏览器,您将看到数据现在已从数据库更新到视图。

更新视图

让我们通过单击“新建”链接从浏览器添加一条记录。它将显示创建视图。

创建视图

让我们在以下字段中添加一些数据。

添加一些数据

单击“创建”按钮,它将更新索引视图并将此新记录添加到数据库中。

新记录数据库

现在让我们进入 SQL Server 对象资源管理器并刷新数据库。右键单击“雇员”表并选择“查看数据”菜单选项。您将看到该记录已添加到数据库中。

添加到数据库中的记录

ASP.NET MVC – 验证

验证是 ASP.NET MVC 应用程序中的一个重要方面。它用于检查用户输入是否有效。ASP.NET MVC 提供了一组易于使用的验证,同时它也是检查错误并在必要时向用户显示消息的强大方法。

干燥

DRY 代表Don’t Repeat Yourself,是 ASP.NET MVC 的核心设计原则之一。从开发的角度来看,鼓励只在一个地方指定功能或行为,然后从那个地方在整个应用程序中使用它。

这减少了您需要编写的代码量,并使您编写的代码不易出错且更易于维护。

向模型添加验证

让我们看一下上一章项目中验证的简单示例。在这个例子中,我们将数据注解添加到我们的模型类中,它提供了一些内置的验证属性集,可以直接应用于您的应用程序中的任何模型类或属性,例如Required、StringLength、RegularExpressionRange验证属性。

它还包含像 DataType 这样的格式化属性,这些属性有助于格式化并且不提供任何验证。验证属性指定您希望对它们所应用的模型属性强制执行的行为。

Required 和 MinimumLength 属性表明一个属性必须有一个值;但是没有什么可以阻止用户输入空白来满足此验证。RegularExpression 属性用于限制可以输入的字符。

让我们通过添加不同的注释属性来更新 Employee 类,如下面的代码所示。

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace MVCSimpleApp.Models {
   public class Employee{
      public int ID { get; set; }
      [StringLength(60, MinimumLength = 3)]
		
      public string Name { get; set; }
      [Display(Name = "Joining Date")]
      [DataType(DataType.Date)]
      [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",
		
      ApplyFormatInEditMode = true)]
      public DateTime JoiningDate { get; set; }
      [Range(22, 60)]
      public int Age { get; set; }
   }
}

现在我们还需要对数据库设置限制。但是,SQL Server 对象资源管理器中的数据库显示名称属性设置为 NVARCHAR (MAX),如下面的屏幕截图所示。

NVARCHAR (MAX)

为了在数据库上设置这个限制,我们将使用迁移来更新架构。

从工具 → NuGet 包管理器 → 包管理器控制台打开包管理器控制台窗口。

包管理器控制台

包管理器控制台窗口中一一输入以下命令

Enable-Migrations
add-migration DataAnnotations
update-database

以下是在包管理器控制台窗口中执行这些命令后的日志。

包管理器控制台窗口

Visual Studio 还将打开派生自 DbMIgration 类的类,您可以在其中看到更新Up方法中架构约束的代码

namespace MVCSimpleApp.Migrations {
   using System;
   using System.Data.Entity.Migrations;
	
   public partial class DataAnnotations : DbMigration{
      public override void Up(){
         AlterColumn("dbo.Employees", "Name", c => c.String(maxLength: 60));
      }
		
      public override void Down(){
         AlterColumn("dbo.Employees", "Name", c => c.String());
      }
   }
}

Name 字段的最大长度为 60,这是数据库中的新长度限制,如下面的快照所示。

新的长度限制

运行此应用程序并通过指定以下 URL http://localhost:63004/Employees/Create转到创建视图

本地主机员工创建

让我们在这些字段中输入一些无效数据,然后单击创建按钮,如下面的屏幕截图所示。

输入无效数据

您将看到 jQuery 客户端验证检测到错误,并且还会显示一条错误消息。

ASP.NET MVC – 安全

在本章中,我们将讨论如何在应用程序中实现安全功能。我们还将了解 ASP.NET 中包含的新成员资格功能,这些功能可从 ASP.NET MVC 中使用。在最新版本的 ASP.NET 中,我们可以通过以下方式管理用户身份 –

  • SQL数据库
  • 本地 Windows 活动目录

在本章中,我们还将了解作为 ASP.NET 一部分的新标识组件,并了解如何为我们的用户和角色自定义成员资格。

验证

用户认证是指验证用户的身份。这真的很重要。出于显而易见的原因,您可能只需要向经过身份验证的用户展示您的应用程序。

让我们创建一个新的 ASP.Net MVC 应用程序。

新建 MVC 应用程序

单击确定继续。

当您启动一个新的 ASP.NET 应用程序时,该过程中的步骤之一是为应用程序需要配置身份验证服务。

选择 MVC 模板,您将看到更改身份验证按钮现已启用。

身份验证按钮已启用

这是通过“新建项目”对话框中显示的“更改身份验证”按钮完成的。默认身份验证是个人用户帐户。

身份验证选项

当您单击更改按钮时,您将看到一个包含四个选项的对话框,如下所示。

无认证

第一个选项是无身份验证,当您想要构建一个不关心访问者是谁的网站时,可以使用此选项。

无认证

它对任何人开放,每个人都像每个页面一样连接。您以后可以随时更改它,但无身份验证选项意味着不会有任何功能来识别访问该网站的用户。

个人用户帐户

第二个选项是个人用户帐户,这是传统的基于表单的身份验证,用户可以在其中访问网站。他们可以注册、创建登录名,并且默认情况下,他们的用户名使用一些新的 ASP.NET 标识功能存储在 SQL Server 数据库中,我们将看到这些功能。

个人用户帐户

密码也存储在数据库中,但它首先被散列。由于密码是散列的,因此您不必担心数据库中的纯文本密码。

此选项通常用于要确定用户身份的 Internet 站点。除了让用户使用密码为您的网站创建本地登录之外,您还可以启用来自第三方(如 Microsoft、Google、Facebook 和 Twitter)的登录。

这允许用户使用他们的 Live 帐户或 Twitter 帐户登录您的站点,他们可以选择本地用户名,但您不需要存储任何密码。

这是我们将在本模块中花一些时间的选项;个人用户帐户选项。

工作和学校帐户

第三个选项是使用组织帐户,这通常用于您将使用 Active Directory 联合服务的业务应用程序。

工作学校帐户

您将设置 Office 365 或使用 Azure Active Directory 服务,并且您可以单点登录内部应用程序和云应用程序。

您还需要提供一个应用程序 ID,以便您的应用程序需要注册到 Windows Azure 管理门户(如果它基于 Azure),并且应用程序 ID 将在所有可能注册的应用程序中唯一标识此应用程序。

Windows 身份验证

第四个选项是 Windows 身份验证,它适用于 Intranet 应用程序。

Windows 身份验证

用户登录到 Windows 桌面并可以启动浏览器访问位于同一防火墙内的应用程序。ASP.NET 可以自动获取用户的身份,即由活动目录建立的身份。此选项不允许对站点进行任何匿名访问,但这也是一个可以更改的配置设置。

让我们来看看基于表单的身份验证,即名称为个人用户帐户的身份验证。此应用程序将在本地 SQL Server 数据库中存储用户名和密码、旧密码,并且在创建此项目时,Visual Studio 还将添加 NuGet 包。

基于表单的身份验证

现在运行此应用程序,当您第一次使用此应用程序时,您将成为匿名用户。

匿名用户

您还没有可以登录的帐户,因此您需要在此站点上注册。

单击注册链接,您将看到以下视图。

点击注册链接

输入您的电子邮件 ID 和密码。

输入EmailId密码

单击注册。现在,应用程序将识别您。

点击注册

它将能够显示您的姓名。在以下屏幕截图中,您可以看到您好,[email protected]被展示。您可以单击它,它是一个指向您可以更改密码的页面的链接。

显示你的名字

您还可以注销、关闭、重新启动、一周后返回,并且您应该能够使用之前使用的凭据登录。现在单击注销按钮,它将显示以下页面。

单击注销按钮

再次单击登录链接,您将进入以下页面。

点击登录链接

您可以使用相同的凭据再次登录。

为了达到这一点,在幕后进行了大量工作。然而,我们想要做的是检查每个功能,看看这个 UI 是如何构建的。什么是管理注销和登录过程?这些信息在数据库中排序在哪里?

让我们从几个简单的基础开始。首先我们将看到这个用户名是如何显示的。从解决方案资源管理器的 View/Shared 文件夹中打开 _Layout.cshtml。

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "utf-8" />
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
      <title>@ViewBag.Title - My ASP.NET Application</title>
      @Styles.Render("~/Content/css")
      @Scripts.Render("~/bundles/modernizr")
   </head>
	
   <body>
      <div class = "navbar navbar-inverse navbar-fixed-top">
         <div class = "container">
			
            <div class = "navbar-header">
               <button type = "button" class = "navbar-toggle" datatoggle = "collapse"
                  data-target = ".navbar-collapse">
                     <span class = "icon-bar"></span>
                     <span class = "icon-bar"></span>
                     <span class = "icon-bar"></span>
               </button>
					
               @Html.ActionLink("Application name", "Index", "Home", new
               { area = "" }, new { @class = "navbar-brand" })
            </div>
				
            <div class = "navbar-collapse collapse">
               <ul class = "nav navbar-nav">
                  <li>@Html.ActionLink("Home", "Index", "Home")</li>
                  <li>@Html.ActionLink("About", "About", "Home")</li>
                  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
               </ul>
					
               @Html.Partial("_LoginPartial")
            </div>
				
         </div>
			
      </div>
      <div class = "container body-content">
         @RenderBody()
         <hr />
         <footer>
            <p>© @DateTime.Now.Year - My ASP.NET Application</p>
         </footer>
      </div>
		
      @Scripts.Render("~/bundles/jquery")
      @Scripts.Render("~/bundles/bootstrap")
      @RenderSection("scripts", required: false)
		
   </body>
</html>

有一个通用的导航栏、应用程序名称、菜单,还有一个正在呈现的名为 _loginpartial 的局部视图。这实际上是显示用户名或注册和登录名的视图。所以 _loginpartial.cshtml 也在共享文件夹中。

@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated) {
   using (Html.BeginForm("LogOff", "Account", FormMethod.Post,
      new { id = "logoutForm", @class = "navbar-right" })){
         @Html.AntiForgeryToken()
         <ul class = "nav navbar-nav navbar-right">
            <li>
               @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!",
               "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
            </li>
				
            <li>
               <a href = "javascript:document.getElementById('logoutForm').submit()">Logoff</a>
            </li>
				
         </ul>
      }
}else{
   <ul class = "nav navbar-nav navbar-right">
      <li>@Html.ActionLink("Register", "Register", "Account", routeValues:
         null, htmlAttributes: new { id = "registerLink" })</li>
			
      <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null,
         htmlAttributes: new { id = "loginLink" })</li>
   </ul>
}

正如您在上面看到的,有 if/else 语句。如果我们不知道用户是谁,因为请求没有经过身份验证,这个视图将显示注册和登录链接。用户可以点击链接进行登录或注册。所有这些都是由帐户控制器完成的。

现在,我们想看看如何获​​取用户名,这在 Request.IsAuthenticated 中。您可以看到对 User.Identity.GetUserName 的调用。这将检索用户名,在本例中为“[email protected]

授权

让我们假设我们有某种类型的信息,我们希望保护这些信息免受未经身份验证的用户的侵害。因此,让我们创建一个新控制器来显示该信息,但仅限于用户登录时。

右键单击控制器文件夹并选择添加 → 控制器。

用户登录

选择一个 MVC 5 控制器 – 空控制器,然后单击“添加”。

输入名称 SecretController 并单击“添加”按钮。

秘密控制器

它将在内部有两个操作,如以下代码所示。

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

运行此应用程序时,您无需任何身份验证即可访问此信息,如下面的屏幕截图所示。

这里的秘密信息

因此,只有经过身份验证的用户才能访问 Secret 操作方法,并且任何人都可以在没有任何身份验证的情况下使用 PublicInfo。

为了保护此特定操作并防止未经身份验证的用户到达此处,您可以使用 Authorize 属性。没有任何其他参数的 Authorize 属性将确保用户的身份是已知的并且他们不是匿名用户。

// GET: Secret
[Authorize]
public ContentResult Secret(){
   return Content("Secret informations here");
}

现在再次运行此应用程序并指定相同的 URL http://localhost:54232/Secret/SecretMVC 应用程序将检测到您无权访问应用程序的该特定区域,并将自动将您重定向到登录页面,在那里您将有机会登录并尝试返回应用程序的该区域你被拒绝的地方。

自动重定向登录页面

可以看到在返回URL中指定了它,它本质上是告诉这个页面,如果用户登录成功,将他们重定向回/secret/secret。

输入您的凭据,然后单击“登录”按钮。您将看到它直接转到该页面。

这里的秘密信息

如果您返回主页并注销,则无法进入机密页面。您将再次被要求登录,但如果转到 /Secret/PublicInfo,即使您未通过身份验证,您也可以看到该页面。

这里的公共信息

因此,当您在几乎所有内容都需要授权的控制器中时,您不想对每个操作都进行授权。在这种情况下,您始终可以将此过滤器应用于控制器本身,现在该控制器内的每个操作都需要对用户进行身份验证。

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

但是,如果您真的希望任何操作处于打开状态,您可以使用另一个属性来覆盖此授权规则,即 AllowAnonymous。

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      [AllowAnonymous]
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

运行此应用程序,您可以通过登录访问 /Secret/PublicInfo,但其他操作将需要身份验证。

这里的公共信息

它将只允许匿名用户进入这一操作。

通过 Authorize 属性,您还可以指定一些参数,例如允许某些特定用户参与此操作。

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize(Users = "[email protected]")]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }
		
      [AllowAnonymous]
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

当您运行此应用程序并转到 /secret/secret 时,它会要求您登录,因为它不是此控制器的正确用户。

进入秘密

ASP.NET MVC – 缓存

在本章中,我们将重点介绍一种最常见的 ASP.NET 技术,例如缓存,以提高应用程序的性能。缓存意味着在内存中存储一​​些经常使用的东西以提供更好的性能。我们将看到如何利用输出缓存显着提高 ASP.NET MVC 应用程序的性能。

在 ASP.NET MVC 中,您可以应用一个 OutputCache 过滤器属性,这与 Web 表单中的输出缓存的概念相同。输出缓存使您能够缓存控制器操作返回的内容。

输出缓存基本上允许您将特定控制器的输出存储在内存中。因此,将来对该控制器中相同操作的任何请求都将从缓存的结果中返回。这样,每次调用相同的控制器操作时都不需要生成相同的内容。

为什么要缓存?

我们需要在许多不同的场景中缓存来提高应用程序的性能。例如,您有一个 ASP.NET MVC 应用程序,它显示一个员工列表。现在,当用户每次调用控制器操作时,通过执行数据库查询从数据库中检索这些记录时,它会返回索引视图。

因此,您可以利用输出缓存来避免每次用户调用相同的控制器操作时都执行数据库查询。在这种情况下,视图将从缓存中检索,而不是从控制器操作中重新生成。

缓存使您能够避免在服务器上执行冗余工作。

让我们看一下我们项目中缓存的一个简单示例。

[OutputCache(Duration = 60)]
public ActionResult Index(){
   var employees = from e in db.Employees
   orderby e.ID
   select e;
   return View(employees);
}

如您所见,我们在 EmployeeController 的索引操作上添加了“OutputCache”属性。现在为了理解这个概念,让我们在调试器模式下运行这个应用程序,并在 Index action 方法中插入一个断点。

输出缓存

指定以下 URL http://localhost:63004/employee,然后按“Enter”。您将看到在 Index 操作方法中命中了断点。

断点被击中

按“F5”按钮继续,您将在视图中看到从数据库中检索到的员工列表。

取回员工名单

60秒内再次刷新浏览器,你会看到这次没有命中断点。这是因为我们使用了持续时间为秒的输出缓存。所以它会缓存这个结果 60 秒,当你刷新浏览器时,它会从缓存中获取结果,并且不会从数据库服务器加载内容。

除了持续时间参数之外,还有其他设置选项可用于输出缓存。这些设置不仅适用于 MVC 框架,而且还继承自 ASP.Net 缓存。

改变输出缓存

在某些情况下,您可能需要不同的缓存版本,例如,当您创建详细信息页面时,当您单击详细信息链接时,您将获得所选员工的详细信息。

但首先我们需要创建详细视图。为此,右键单击 EmployeeController 中的 Details 操作方法,然后选择 Add View…

创建详细视图

您将看到默认情况下选择了详细信息名称。现在从模板下拉列表中选择详细信息,从模型类下拉列表中选择员工。

模板下拉菜单

单击“添加”继续,您将看到 Details.cshtml。

@model MVCSimpleApp.Models.Employee
@{
   Layout = null;
}

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Details</title>
   </head>
	
   <body>
      <div>
         <h4>Employee</h4>
         <hr />
         <dl class = "dl-horizontal">
            <dt>
               @Html.DisplayNameFor(model => model.Name)
            </dt>
				
            <dd>
               @Html.DisplayFor(model => model.Name)
            </dd>
				
            <dt>
               @Html.DisplayNameFor(model => model.JoiningDate)
            </dt>
				
            <dd>
               @Html.DisplayFor(model => model.JoiningDate)
            </dd>
				
            <dt>
               @Html.DisplayNameFor(model => model.Age)
            </dt>
				
            <dd>
               @Html.DisplayFor(model => model.Age)
            </dd>
				
         </dl>
      </div>
		
      <p>
         @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
         @Html.ActionLink("Back to List", "Index")
      </p>
		
   </body>
</html>

您可以利用 [OutputCache] 属性的 VaryByParam 属性。当表单参数或查询字符串参数变化时,此属性使您能够创建相同内容的不同缓存版本。下面是Details动作的实现。

// GET: Employee/Details/5
[OutputCache(Duration = int.MaxValue, VaryByParam = "id")]

public ActionResult Details(int id){
   var employee = db.Employees.SingleOrDefault(e => e.ID == id);
   return View(employee);
}

编译并执行上述代码后,您将通过指定 URL http://localhost:63004/employee收到以下输出

创建新的

单击任何链接的详细信息链接,您将看到该特定员工的详细信息视图。

特定员工详情

Details() 操作包括一个值为“Id”的 VaryByParam 属性。当 Id 参数的不同值传递给控制器​​操作时,会生成详细信息视图的不同缓存版本。

了解使用 VaryByParam 属性会导致更多缓存很重要。为每个不同版本的 Id 参数创建一个不同的 Details 视图缓存版本。

缓存配置文件

您可以在 web.config 文件中创建缓存配置文件。它是通过修改 [OutputCache] 属性的属性来配置输出缓存属性的替代方法。它提供了以下几个重要优点。

  • 控制控制器操作如何在一个中央位置缓存内容。

  • 创建一个缓存配置文件并将该配置文件应用于多个控制器或控制器操作。

  • 在不重新编译应用程序的情况下修改 Web 配置文件。

  • 禁用已部署到生产的应用程序的缓存。

让我们通过在 web.config 文件中创建缓存配置文件来查看缓存配置文件的简单示例。<caching> 部分必须出现在 <system.web> 部分中。

<caching>
   <outputCacheSettings>
      <outputCacheProfiles>
         <add name = "Cache10Min" duration = "600" varyByParam = "none"/>
      </outputCacheProfiles>
   </outputCacheSettings>
</caching>

您可以将 Cache10Min 配置文件应用到具有 [OutputCache] 属性的控制器操作,如下所示。

[OutputCache(CacheProfile = "Cache10Min")]

public ActionResult Index(){
   var employees = from e in db.Employees
   orderby e.ID
   select e;
   return View(employees);
}

运行此应用程序并指定以下 URL http://localhost:63004/employee

调用索引操作

如果您如上所示调用 Index() 操作,则将返回相同的时间 10 分钟。

ASP.NET MVC – Razor

在本章中,我们将了解 ASP.NET MVC 应用程序中的 Razor 视图引擎以及 Razor 存在的一些原因。Razor 是一种标记语法,可让您使用 C# 和 VB.Net 将基于服务器的代码嵌入到网页中。它不是一种编程语言。它是一种服务器端标记语言。

Razor 与 ASP.NET MVC 没有关系,因为 Razor 是一个通用模板引擎。您可以在任何地方使用它来生成 HTML 等输出。只是 ASP.NET MVC 实现了一个视图引擎,允许我们在 MVC 应用程序中使用 Razor 来生成 HTML。

查看引擎

您将拥有一个混合了一些文字文本和一些代码块的模板文件。您将该模板与一些数据或特定模型结合起来,其中模板指定数据应该出现的位置,然后执行该模板以生成输出。

Razor 与 ASPX

  • Razor 与 ASPX 文件的工作方式非常相似。ASPX 文件是模板,其中包含文字文本和一些指定数据应显示位置的 C# 代码。我们执行这些来为我们的应用程序生成 HTML。

  • ASPX 文件依赖于 ASP.NET 运行时可用于解析和执行这些 ASPX 文件。Razor 没有这样的依赖。

  • 与 ASPX 文件不同,Razor 有一些不同的设计目标。

目标

微软希望 Razor 易于使用和学习,并在 Visual Studio 等工具中工作,以便 IntelliSense 可用,调试器可用,但他们希望 Razor 与特定技术无关,如 ASP.NET 或ASP.NET MVC。

如果您熟悉 ASPX 文件的生命周期,那么您可能知道依赖 ASP.NET 运行时可用于解析和执行这些 ASPX 文件。微软希望 Razor 更智能,让开发人员的工作更轻松。

让我们看一下来自 ASPX 文件的示例代码,其中包含一些文字文本。这是我们的 HTML 标记。它还包含少量 C# 代码。

<% foreach (var item in Model) { %>
   <tr>
      <td>
         <%: Html.ActionLink("Edit", "Edit", new { id = item.ID })%> |
         <%: Html.ActionLink("Details", "Details", new { id = item.ID }) %>|
         <%: Html.ActionLink("Delete", "Delete", new { id = item.ID })%>
      </td>
		
      <td>
         <%: item.Name %>
      </td>
		
      <td>
         <%: String.Format("{0,g}", item.JoiningDate) %>
      </td>
		
   </tr>
<%}%>

但是这些 Web 表单基本上被 Microsoft 重新利用以与早期版本的 MVC 一起使用,这意味着 ASPX 文件从来都不是 MVC 的完美匹配。

当您需要从 C# 代码转换回 HTML 以及从 HTML 代码转换回 C# 代码时,语法有点笨拙。IntelliSense 还会提示您做一些在 MVC 项目中没有意义的事情,例如将输出缓存和用户控件的指令添加到 ASPX 视图中。

现在看看这个产生相同输出的代码,不同之处在于它使用了 Razor 语法。

@foreach (var item in Model) {
   <tr>
      <td>
         @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
         @Html.ActionLink("Details", "Details", new { id = item.ID }) |
         @Html.ActionLink("Delete", "Delete", new { id = item.ID })
      </td>
		
      <td>
         @item.Name
      </td>
		
      <td>
         @String.Format("{0,g}", item.JoiningDate)
      </td>
   </tr>
}

使用 Razor 语法,您可以使用“@”符号开始一些 C# 代码,Razor 解析将自动切换到解析这个语句,这个 foreach 语句,作为一点 C# 代码。

但是当我们完成 foreach 语句并且我们有了左花括号时,我们可以从 C# 代码转换为 HTML,而无需在其中放置显式标记,例如尖括号符号中的百分比。

Razor 解析器足够智能,可以在 C# 代码和 HTML 之间切换,当我们需要将右花括号放在这里时,可以再次从 HTML 切换回 C# 代码。如果您比较这两个代码块,我想您会同意 Razor 版本更易于阅读和编写。

使用 Razor 创建视图

让我们创建一个新的 ASP.Net MVC 项目。

Razor MVC 项目

在名称字段中输入项目名称,然后单击确定。

项目名称

为简单起见,请选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。它将创建一个具有最少预定义内容的基本 MVC 项目。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。由于我们已经从一个空的项目模板创建了 ASP.Net MVC 项目,因此目前该应用程序不包含任何要运行的内容。由于我们从一个空的应用程序开始,甚至没有一个控制器,让我们添加一个 HomeController。

要添加控制器,请右键单击解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。它将显示“添加脚手架”对话框。

剃刀控制器文件夹

选择MVC 5 Controller – Empty选项并单击 Add 按钮,然后将出现 Add Controller 对话框。

家庭控制器

将名称设置为 HomeController 并单击“添加”按钮。您将在 Controllers 文件夹中看到一个新的 C# 文件“HomeController.cs”,该文件也已打开以在 Visual Studio 中进行编辑。

在 Visual Studio 中编辑

右键单击索引操作并选择添加视图…

索引操作添加视图

从模板下拉列表中选择空,然后单击添加按钮。Visual Studio 将在View/Home文件夹中创建一个 Index.cshtml 文件

创建索引.cshtml

请注意,Razor 视图有一个 cshtml 扩展名。如果您使用 Visual Basic 构建 MVC 应用程序,它将是一个 VBHTML 扩展。这个文件的顶部是一个代码块,它显式地将此 Layout 属性设置为 null。

当您运行此应用程序时,您将看到空白网页,因为我们已经从空模板创建了一个视图。

空白网页

让我们添加一些 C# 代码,让事情变得更有趣。要在 Razor 视图中编写一些 C# 代码,我们要做的第一件事是键入“@”符号,告诉解析器它将在代码中执行某些操作。

让我们创建一个 FOR 循环,在花括号内指定 ‘@i’,这实质上是告诉 Razor 放置 i 的值。

@{
   Layout = null;
} 

<!DOCTYPE html>
<html>
   <head>
      <meta name = "viewport" content = "width = device-width" />
      <title>Index</title>
   </head>
	
   <body>
      <div>
         @for (int index = 0; index < 12; index++){
            <div>@index </div>
         }
      </div>
   </body>
	
</html>

运行此应用程序,您将看到以下输出。

剃刀输出

ASP.NET MVC – 数据注释

DataAnnotations 用于配置您的模型类,这将突出显示最常用的配置。许多 .NET 应用程序(例如 ASP.NET MVC)也理解 DataAnnotations,这允许这些应用程序利用相同的注释进行客户端验证。DataAnnotation 属性会覆盖默认的 Code-First 约定。

System.ComponentModel.DataAnnotations包括以下影响列的可为空性或大小的属性。

  • 钥匙
  • 时间戳
  • 并发检查
  • 必需的
  • 最小长度
  • 最长长度
  • 字符串长度

System.ComponentModel.DataAnnotations.Schema命名空间包括以下影响数据库架构的属性。

  • 桌子
  • 柱子
  • 指数
  • 外键
  • 未映射
  • 反性质

钥匙

实体框架依赖于每个具有用于跟踪实体的键值的实体。Code First 依赖的约定之一是它如何暗示哪个属性是每个 Code First 类中的键。

约定是查找名为“Id”的属性或将类名和“Id”组合在一起的属性,例如“StudentId”。该属性将映射到数据库中的主键列。Student、Course 和 Enrollment 类都遵循此约定。

现在让我们假设 Student 类使用名称 StdntID 而不是 ID。当 Code First 找不到与此约定匹配的属性时,它将抛出异常,因为 Entity Framework 要求您必须具有键属性。

您可以使用键注释来指定将哪个属性用作 EntityKey。

让我们看一下包含 StdntID 的 Student 类。它不遵循默认的 Code First 约定,因此为了处理这个问题,添加了 Key 属性,这将使其成为主键。

public class Student{
   [Key]
   public int StdntID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

当您运行应用程序并在 SQL Server 资源管理器中查看数据库时,您将看到主键现在是 Students 表中的 StdntID。

主键 StdntID

实体框架还支持复合键。复合键是由多个属性组成的主键。例如,您有一个 DrivingLicense 类,其主键是 LicenseNumber 和 IssuingCountry 的组合。

public class DrivingLicense{
   [Key, Column(Order = 1)]
   public int LicenseNumber { get; set; }
	
   [Key, Column(Order = 2)]
   public string IssuingCountry { get; set; }
   public DateTime Issued { get; set; }
   public DateTime Expires { get; set; }
}

当您有复合键时,实体框架要求您定义键属性的顺序。您可以使用 Column 注释来指定顺序。

复合键

时间戳

Code First 会将 Timestamp 属性视为 ConcurrencyCheck 属性,但它还会确保 Code First 生成的数据库字段不可为空。

更常见的是使用 rowversion 或时间戳字段进行并发检查。但是,您可以使用更具体的 TimeStamp 注释,而不是使用 ConcurrencyCheck 注释,只要属性的类型是字节数组即可。在给定的类中只能有一个时间戳属性。

让我们通过将 TimeStamp 属性添加到 Course 类来查看一个简单示例。

public class Course{
   public int CourseID { get; set; }
   public string Title { get; set; }
   public int Credits { get; set; }
   [Timestamp]
   public byte[] TStamp { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

正如您在上面的示例中看到的,Timestamp 属性应用于 Course 类的 Byte[] 属性。因此,Code First 将在 Courses 表中创建一个时间戳列 TStamp。

并发检查

ConcurrencyCheck 注释允许您在用户编辑或删除实体时标记一个或多个用于数据库中并发检查的属性。如果您一直在使用 EF 设计器,这与将属性的 ConcurrencyMode 设置为 Fixed 一致。

让我们看一个简单的例子,通过将 ConcurrencyCheck 添加到 Course 类的 Title 属性来看看它是如何工作的。

public class Course{
   public int CourseID { get; set; }
	
   [ConcurrencyCheck]
   public string Title { get; set; }
   public int Credits { get; set; }
	
   [Timestamp, DataType("timestamp")]
   public byte[] TimeStamp { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

在上面的 Course 类中, ConcurrencyCheck 属性应用于现有的 Title 属性。Code First 将在更新命令中包含 Title 列以检查乐观并发,如以下代码所示。

exec sp_executesql N'UPDATE [dbo].[Courses]
   SET [Title] = @0
   WHERE (([CourseID] = @1) AND ([Title] = @2))
   ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max)
',@0 = N'Maths',@1 = 1,@2 = N'Calculus'
go

必需的

Required 注释告诉 EF 需要一个特定的属性。让我们看一下下面的 Student 类,其中将 Required id 添加到 FirstMidName 属性。必需属性将强制 EF 确保该属性中包含数据。

public class Student{
   [Key]
   public int StdntID { get; set; }
	
   [Required]
   public string LastName { get; set; }
	
   [Required]
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

您可以在上面的示例中看到 Student 类的 Required 属性应用于 FirstMidName 和 LastName。因此,Code First 将在 Students 表中创建一个 NOT NULL FirstMidName 和 LastName 列,如下面的屏幕截图所示。

学生桌

最长长度

MaxLength 属性允许您指定其他属性验证。它可以应用于域类的字符串或数组类型属性。EF Code First 将设置列的大小,如 MaxLength 属性中指定的那样。

让我们看看下面的 Course 类,其中 MaxLength(24) 属性应用于 Title 属性。

public class Course{
   public int CourseID { get; set; }
   [ConcurrencyCheck]
   [MaxLength(24)]
	
   public string Title { get; set; }
   public int Credits { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

当您运行上述应用程序时,Code-First 将在 Coursed 表中创建一个 nvarchar(24) 列 Title,如下面的屏幕截图所示。

列标题课程表

现在,当用户设置包含超过 24 个字符的标题时,EF 将抛出 EntityValidationError。

最小长度

MinLength 属性允许您指定其他属性验证,就像您对 MaxLength 所做的一样。MinLength 属性也可以与 MaxLength 属性一起使用,如下面的代码所示。

public class Course{
   public int CourseID { get; set; }
   [ConcurrencyCheck]
   [MaxLength(24) , MinLength(5)]
   public string Title { get; set; }
   public int Credits { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

如果您设置的 Title 属性值小于 MinLength 属性中指定的长度或大于 MaxLength 属性中的指定长度,EF 将抛出 EntityValidationError。

字符串长度

StringLength 还允许您指定其他属性验证,如 MaxLength。不同之处在于 StringLength 属性只能应用于域类的字符串类型属性。

public class Course{
   public int CourseID { get; set; }
   [StringLength (24)]
   public string Title { get; set; }
   public int Credits { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

实体框架还验证 StringLength 属性的属性值。现在,如果用户设置的标题包含超过 24 个字符,则 EF 将抛出 EntityValidationError。

桌子

默认代码优先约定创建一个与类名相同的表名。如果您让 Code First 创建数据库,您还可以更改它正在创建的表的名称。您可以将 Code First 与现有数据库一起使用。但是,类的名称并不总是与数据库中表的名称相匹配。

表属性覆盖此默认约定。EF Code First 将为给定的域类在 Table 属性中创建一个具有指定名称的表。

让我们看一个示例,其中类名为 Student,按照惯例,Code First 假定这将映射到名为 Students 的表。如果不是这种情况,您可以使用 Table 属性指定表的名称,如以下代码所示。

[Table("StudentsInfo")]
public class Student{
   [Key]
   public int StdntID { get; set; }
	
   [Required]
   public string LastName { get; set; }
	
   [Required]
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

您现在可以看到 Table 属性将表指定为 StudentsInfo。生成表后,您将看到表名 StudentsInfo,如下面的屏幕截图所示。

表名 StudentsInfo

您不仅可以指定表名,还可以使用 Table 属性使用以下代码为表指定架构。

[Table("StudentsInfo", Schema = "Admin")]

public class Student{
   [Key]
   public int StdntID { get; set; }
	
   [Required]
   public string LastName { get; set; }
	
   [Required]
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

在上面的例子中,表是用管理模式指定的。现在 Code First 将在 Admin 模式中创建 StudentsInfo 表,如下面的屏幕截图所示。

管理架构中的 StudentsInfo 表

柱子

它也与 Table 属性相同,但 Table 属性会覆盖表行为,而 Column 属性会覆盖列行为。默认代码优先约定创建与属性名称相同的列名称。

如果您让 Code First 创建数据库,并且您还想更改表中列的名称。列属性覆盖此默认约定。EF Code First 将在 Column 属性中为给定属性创建一个具有指定名称的列。

让我们再次看一下下面的示例,其中属性名为 FirstMidName,按照惯例,Code First 假定这将映射到名为 FirstMidName 的列。如果不是这种情况,您可以使用 Column 属性指定列的名称,如以下代码所示。

public class Student{
   public int ID { get; set; }
   public string LastName { get; set; }
	
   [Column("FirstName")]
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

您现在可以看到 Column 属性将列指定为 FirstName。生成表后,您将看到列名 FirstName,如下面的屏幕截图所示。

列名名字

指数

Index 属性是在 Entity Framework 6.1 中引入的。注意– 如果您使用的是早期版本,则本节中的信息不适用。

您可以使用 IndexAttribute 在一个或多个列上创建索引。将属性添加到一个或多个属性会导致 EF 在创建数据库时在数据库中创建相应的索引。

在大多数情况下,索引使数据检索更快更有效。但是,使用索引重载表或视图可能会令人不快地影响其他操作(例如插入或更新)的性能。

索引是实体框架中的新功能,您可以通过减少从数据库查询数据所需的时间来提高 Code First 应用程序的性能。

您可以使用 Index 属性向数据库添加索引,并覆盖默认的 Unique 和 Clustered 设置以获得最适合您的方案的索引。默认情况下,索引将命名为 IX_<property name>

让我们看一下下面的代码,其中为 Credits 在 Course 类中添加了 Index 属性。

public class Cours{
   public int CourseID { get; set; }
   public string Title { get; set; }
   [Index]
   public int Credits { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

您可以看到 Index 属性应用于 Credits 属性。现在生成表时,您将在索引中看到 IX_Credits。

IX_Credits 索引

默认情况下,索引是非唯一的,但您可以使用IsUnique命名参数来指定索引应该是唯一的。以下示例引入了一个唯一索引,如以下代码所示。

public class Course{
   public int CourseID { get; set; }
   [Index(IsUnique = true)]
	
   public string Title { get; set; }
   [Index]
	
   public int Credits { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

外键

Code First 约定将处理模型中最常见的关系,但在某些情况下需要帮助。例如,通过更改 Student 类中关键属性的名称,会导致其与 Enrollment 类的关系出现问题。

public class Enrollment{
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }
   public virtual Course Course { get; set; }
   public virtual Student Student { get; set; }
}

public class Student{
   [Key]
   public int StdntID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

在生成数据库时,Code First 会看到 Enrollment 类中的 StudentID 属性,并按照惯例将其识别为与类名加“ID”相匹配,作为 Student 类的外键。但是 Student 类中没有 StudentID 属性,而是 Student 类中的 StdntID 属性。

对此的解决方案是在 Enrollment 中创建导航属性,并使用 ForeignKey DataAnnotation 来帮助 Code First 了解如何构建两个类之间的关系,如下代码所示。

public class Enrollment{
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }
   public virtual Course Course { get; set; }
	
   [ForeignKey("StudentID")]
   public virtual Student Student { get; set; }
}

您现在可以看到 ForeignKey 属性应用于导航属性。

外键属性

未映射

默认情况下,Code First 的每个属性都是受支持的数据类型,包括 getter 和 setter,都在数据库中表示。但在应用程序中并非总是如此。NotMapped 属性覆盖此默认约定。例如,您可能在 Student 类中有一个属性,例如 FatherName,但它不需要存储。您可以将 NotMapped 属性应用于您不想在数据库中创建列的 FatherName 属性。以下是代码。

public class Student{
   [Key]
   public int StdntID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
   [NotMapped]
   public int FatherName { get; set; }

   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

您可以看到 NotMapped 属性应用于 FatherName 属性。现在生成表时,您将看到不会在数据库中创建FatherName 列,但它存在于Student 类中。

父亲姓名列已创建

Code First 不会为没有 getter 或 setter 的属性创建列。

反性质

InverseProperty 在类之间有多个关系时使用。在 Enrollment 类中,您可能想要跟踪谁注册了当前课程和谁注册了以前的课程。

让我们为 Enrollment 类添加两个导航属性。

public class Enrollment{
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }
	
   public virtual Course CurrCourse { get; set; }
   public virtual Course PrevCourse { get; set; }
   public virtual Student Student { get; set; }
}

同样,您还需要添加这些属性引用的 Course 类。Course 类具有返回 Enrollment 类的导航属性,其中包含所有当前和以前的注册。

public class Course{
   public int CourseID { get; set; }
   public string Title { get; set; }
   [Index]
	
   public int Credits { get; set; }
   public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
   public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}

如果外键属性未包含在特定类中(如上述类所示),则 Code First 会创建 {Class Name}_{Primary Key} 外键列。生成数据库后,您将看到许多外键,如下面的屏幕截图所示。

外键数

如您所见,Code First 无法单独匹配两个类中的属性。Enrollments 的数据库表应该有一个用于 CurrCourse 的外键和一个用于 PrevCourse 的外键,但是 Code First 将创建四个外键属性,即

  • CurrCourse_CourseID
  • PrevCourse_CourseID
  • Course_CourseID
  • Course_CourseID1

要解决这些问题,您可以使用 InverseProperty 注释来指定属性的对齐方式。

public class Course{
   public int CourseID { get; set; }
   public string Title { get; set; }
	
   [Index]
   public int Credits { get; set; }
	
   [InverseProperty("CurrCourse")]
   public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
	
   [InverseProperty("PrevCourse")]
   public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}

如您所见,当 InverseProperty 属性通过指定其所属 Enrollment 类的引用属性应用于上述 Course 类时,Code First 将生成数据库并仅在 Enrollments 表中创建两个外键列,如下面的屏幕截图所示。

外键注册表

我们建议您执行上述示例以更好地理解。

ASP.NET MVC – NuGet 包管理

在本章中,我们将讨论 NuGet,它是 .NET 和 Visual Studio 的包管理器。NuGet 可用于查找和安装包,即软件片段和程序集以及您要在项目中使用的内容。

NuGet 不是特定于 ASP.NET MVC 项目的工具。这是一个可以在 Visual Studio 内部用于控制台应用程序、WPF 应用程序、Azure 应用程序和任何类型的应用程序的工具。

包管理

NuGet 是一个包管理器,负责下载、安装、更新和配置系统中的软件。从术语软件来看,我们不是指最终用户软件,如 Microsoft Word 或 Notepad 2 等,而是指您希望在项目中使用的软件组件,即程序集引用。

例如,您要使用的程序集可能是模拟的,用于模拟对象单元测试,或用于数据访问的 NHibernate,以及您在构建应用程序时使用的组件。上述组件是开源软件,但您找到的一些 NuGet 包是闭源软件。您会发现一些软件包甚至是由 Microsoft 生产的。

上面提到的所有包(如 mock 和 NHibernate)以及 Microsoft 包(如实体框架的预览版)的共同主题是默认情况下它们不随 Visual Studio 一起提供。

没有 NuGet

要在不使用 NuGet 的情况下安装任何这些组件,您需要执行以下步骤。

没有 NuGet 的组件

如果您想使用这些组件之一,您需要找到某个特定项目的主页并查找下载链接。然后,一旦下载了项目,它通常是 ZIP 格式,因此您需要将其解压缩。

如果您没有下载二进制文件,那么您首先需要构建软件,然后在您的项目中引用它。那时许多组件仍然需要一些配置才能启动和运行。

使用 NuGet

NuGet 替换了之前讨论的所有步骤,您只需说添加包。NuGet 知道从哪里下载最新版本,知道如何提取它,如何建立对该组件的引用,甚至对其进行配置。这让您有更多时间来构建软件。

让我们看一个简单的示例,在该示例中,我们将使用 NuGet 在我们的 ASP.NET MVC 项目中添加对实体框架的支持。

步骤 1 – 安装实体框架。右键单击该项目并选择 NuGet 包管理器 → 管理解决方案的 NuGet 包…

选择 NuGet 包管理器

它将打开 NuGet 包管理器。

第 2 步– 在搜索框中搜索实体框架。

搜索实体框架

第 3 步– 选择实体框架并单击“安装”按钮。它将打开“预览”对话框。

预览对话框

步骤 4 – 单击确定继续。

预览对话框单击确定

步骤 5 – 单击“我接受”按钮开始安装。

我接受安装

安装实体框架后,您将在窗口中看到如上所示的消息。

使用 NuGet 安装包时,您将在托管项目的解决方案文件所在的文件夹中看到一个新的包目录。此包目录包含您为该解决方案中的任何项目安装的所有包。

项目中的所有包

换句话说,NuGet 不是将包下载到一个中心位置,而是在每个解决方案的基础上存储它们。

ASP.NET MVC – Web API

ASP.NET Web API 是一个框架,可让您轻松构建可访问各种客户端(包括浏览器和移动设备)的 HTTP 服务。ASP.NET Web API 是在 .NET Framework 上构建 RESTful 应用程序的理想平台。

在 Web 上构建 API 时,可以通过多种方式在 Web 上构建 API。其中包括 HTTP/RPC,这意味着在远程过程调用中使用 HTTP 来通过 Web 调用诸如方法之类的东西。

动词本身包含在 API 中,例如获取客户、插入发票、删除客户,并且这些端点中的每一个最终都是一个单独的 URI。

让我们通过创建一个新的 ASP.NET Web 应用程序来看看一个简单的 Web API 示例。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

Visual Studio 单击文件

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序

在名称字段中输入项目名称 WebAPIDemo,然后单击确定继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

网络API演示

第 4 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 Web API 复选框,然后单击“确定”。

第 5 步– 它将创建一个具有最少预定义内容的基本 MVC 项目。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。

第 6 步– 现在我们需要添加一个模型。右键单击解决方案资源管理器中的模型文件夹,然后选择添加 → 类。

添加模型

您现在将看到“添加新项目”对话框。

添加项目对话框

步骤 7 – 在中间盘中选择 Class 并在 name 字段中输入 Employee.cs。

步骤 8 – 使用以下代码向 Employee 类添加一些属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebAPIDemo.Models {
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
}

步骤 9 – 让我们添加控制器。右键单击解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

它将显示“添加脚手架”对话框。

选择添加控制器

步骤 10 – 选择 Web API 2 控制器 – 空选项。此模板将为控制器创建一个带有默认操作的 Index 方法。

步骤 11 – 单击“添加”按钮,将出现“添加控制器”对话框。

 添加按钮控制器

第 12 步– 将名称设置为 EmployeesController 并单击“添加”按钮。

您将在 Controllers 文件夹中看到一个新的 C# 文件“EmployeeController.cs”,该文件已打开,可在 Visual Studio 中使用一些默认操作进行编辑。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web.Http;
using WebAPIDemo.Models;

namespace WebAPIDemo.Controllers{
   public class EmployeesController : ApiController{
      Employee[] employees = new Employee[]{
         new Employee { ID = 1, Name = "Mark", JoiningDate =
            DateTime.Parse(DateTime.Today.ToString()), Age = 30 },
         new Employee { ID = 2, Name = "Allan", JoiningDate =
            DateTime.Parse(DateTime.Today.ToString()), Age = 35 },
         new Employee { ID = 3, Name = "Johny", JoiningDate =
            DateTime.Parse(DateTime.Today.ToString()), Age = 21 }
      };
		
      public IEnumerable<Employee> GetAllEmployees(){
         return employees;
      }
		
      public IHttpActionResult GetEmployee(int id){
         var employee = employees.FirstOrDefault((p) => p.ID == id);
         if (employee == null){
            return NotFound();
         }
         return Ok(employee);
      }
   }
}

第 13 步– 运行此应用程序并在 URL 末尾指定 /api/employees/ 并按“Enter”。您将看到以下输出。

指定 API 员工

第 14 步– 让我们指定以下 URL http://localhost:63457/api/employees/1,您将看到以下输出。

本地主机 API 员工

ASP.NET MVC – 脚手架

ASP.NET Scaffolding 是用于 ASP.NET Web 应用程序的代码生成框架。Visual Studio 2013 包括用于 MVC 和 Web API 项目的预安装代码生成器。当您想要快速添加与数据模型交互的代码时,您可以向项目添加脚手架。使用脚手架可以减少在项目中开发标准数据操作的时间。

如您所见,我们已经为索引、创建、编辑操作创建了视图,并且还需要更新操作方法。但是 ASP.Net MVC 提供了一种更简单的方法来使用脚手架创建所有这些视图和操作方法。

我们来看一个简单的例子。我们将创建包含模型类 Employee 的相同示例,但这次我们将使用脚手架。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

新建对话框

步骤 2 – 从左侧窗格中,选择模板 → Visual C# → Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称“MVCScaffoldingDemo”,然后单击“确定”继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVC脚手架演示

第 5 步– 为简单起见,选择“空”选项并选中“添加文件夹和核心引用”部分中的 MVC 复选框,然后单击“确定”。

它将创建一个具有最少预定义内容的基本 MVC 项目。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。

Visual Studio 创建的项目

添加实体框架支持

第一步是安装实体框架。右键单击该项目并选择 NuGet 包管理器 → 管理解决方案的 NuGet 包…

NuGet 包管理器

它将打开“NuGet 包管理器”。在搜索框中搜索实体框架。

实体框架搜索框

选择实体框架并单击“安装”按钮。它将打开“预览”对话框。

打开预览对话框

单击确定继续。

单击确定继续

单击“我接受”按钮开始安装。

我接受按钮安装

安装实体框架后,您将在输出窗口中看到消息,如上面的屏幕截图所示。

添加模型

要添加模型,请右键单击解决方案资源管理器中的模型文件夹,然后选择添加 → 类。您将看到“添加新项目”对话框。

项目对话框

选择中间盘中的 Class 并在 name 字段中输入 Employee.cs。

使用以下代码向 Employee 类添加一些属性。

using System;

namespace MVCScaffoldingDemo.Models {
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
}

添加数据库上下文

我们有一个员工模型,现在我们需要添加另一个类,它将与实体框架通信以检索和保存数据。以下是 Employee.cs 文件中的完整代码。

using System;
using System.Data.Entity;

namespace MVCScaffoldingDemo.Models{
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
	
   public class EmpDBContext : DbContext{
      public DbSet<Employee> Employees { get; set; }
   }
}

如您所见,“EmpDBContext”派生自称为“DbContext”的 EF 类。在这个类中,我们有一个名为 DbSet 的属性,它基本上代表您要查询和保存的实体。

现在让我们构建一个解决方案,当项目构建成功时,您将看到消息。

项目成功构建

添加脚手架项目

要添加脚手架,请右键单击解决方案资源管理器中的 Controllers 文件夹,然后选择添加 → 新建脚手架项。

新的脚手架项目

它将显示“添加脚手架”对话框。

显示脚手架对话框

选择带有视图的 MVC 5 Controller,在中间窗格中使用实体框架,然后单击“添加”按钮,这将显示“添加控制器”对话框。

实体框架中间窗格

从模型类下拉列表中选择 Employee,从数据上下文类下拉列表中选择 EmpDBContext。您还将看到默认情况下选择了控制器名称。

单击“添加”按钮继续,您将在 Visual Studio 使用 Scaffolding 创建的 EmployeesController 中看到以下代码。

using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using MVCScaffoldingDemo.Models;

namespace MVCScaffoldingDemo.Controllers {
   public class EmployeesController : Controller{
      private EmpDBContext db = new EmpDBContext();
      
      // GET: Employees
      public ActionResult Index(){
         return View(db.Employees.ToList());
      }
      
      // GET: Employees/Details/5
      public ActionResult Details(int? id){
         if (id == null){
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
         }
			
         Employee employee = db.Employees.Find(id);
			
         if (employee == null){
            return HttpNotFound();
         }
         return View(employee);
      }
      
      // GET: Employees/Create
      public ActionResult Create(){
         return View();
      }
      
      // POST: Employees/Create
      // To protect from overposting attacks, please enable the specific
      properties you want to bind to, for
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
		
      public ActionResult Create([Bind(Include = "ID,Name,JoiningDate,Age")]
      Employee employee){
         if (ModelState.IsValid){
            db.Employees.Add(employee);
            db.SaveChanges();
            return RedirectToAction("Index");
         }
         return View(employee);
      }
      
      // GET: Employees/Edit/5
      public ActionResult Edit(int? id){
         if (id == null){
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
         }
			
         Employee employee = db.Employees.Find(id);
			
         if (employee == null){
            return HttpNotFound();
         }
         return View(employee);
      }
      
      // POST: Employees/Edit/5
      // To protect from overposting attacks, please enable the specific
      properties you want to bind to, for
      // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Edit([Bind(Include = "ID,Name,JoiningDate,Age")]Employee employee){
         if (ModelState.IsValid){
            db.Entry(employee).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
         }
         return View(employee);
      }
      
      // GET: Employees/Delete/5
      public ActionResult Delete(int? id){
         if (id == null){
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
         }
			
         Employee employee = db.Employees.Find(id);
			
         if (employee == null){
            return HttpNotFound();
         }
         return View(employee);
      }
      
      // POST: Employees/Delete/5
      [HttpPost, ActionName("Delete")]
      [ValidateAntiForgeryToken]
		
      public ActionResult DeleteConfirmed(int id){
         Employee employee = db.Employees.Find(id);
         db.Employees.Remove(employee);
         db.SaveChanges();
         return RedirectToAction("Index");
      }
      
      protected override void Dispose(bool disposing){
         if (disposing){
            db.Dispose();
         }
			
         base.Dispose(disposing);
      }
   }
}

运行您的应用程序并指定以下 URL http://localhost:59359/employees您将看到以下输出。

运行您的应用程序

可以看到 View 中没有数据,因为我们还没有向数据库添加任何记录,该数据库是由 Visual Studio 创建的。

让我们通过单击“新建”链接从浏览器添加一条记录,它将显示“创建”视图。

点击新建

让我们在以下字段中添加一些数据。

在字段中添加数据

单击“创建”按钮,它将更新索引视图。

更新索引视图

您可以看到新记录也被添加到数据库中。

添加了新记录

如您所见,我们使用 Scaffolding 实现了相同的示例,这是从模型类创建 Views 和 Action 方法的更简单的方法。

ASP.NET MVC – 引导程序

在本章中,我们将介绍 Bootstrap,它是一个前端框架,现在包含在 ASP.NET 和 MVC 中。它是一种流行的 Web 应用程序前端工具包,可帮助您使用 HTML、CSS 和 JavaScript 构建用户界面。

它最初是由 Twitter 的 Web 开发人员创建供个人使用的,但是,它现在是一个开源软件,并因其灵活性和易用性而受到设计人员和开发人员的欢迎。

您可以使用 Bootstrap 创建一个界面,该界面在从大型桌面显示器到小型移动屏幕的所有内容上都看起来不错。在本章中,我们还将了解 Bootstrap 如何与您的布局视图一起工作以构建应用程序的外观。

Bootstrap 提供了布局、按钮、表单、菜单、小部件、图片轮播、标签、徽章、排版和各种功能所需的所有部分。由于 Bootstrap 全是 HTML、CSS 和 JavaScript,都是开放标准,因此您可以将它与任何框架一起使用,包括 ASP.NET MVC。当你开始一个新的 MVC 项目时,Bootstrap 将会出现,这意味着你会在你的项目中找到 Bootstrap.css 和 Bootstrap.js。

让我们创建一个新的 ASP.NET Web 应用程序。

ASP.NET Web 应用程序

输入项目名称,假设为“MVCBootstrap”,然后单击“确定”。您将看到以下对话框。

MVC 引导程序

在此对话框中,如果您选择空模板,您将获得一个空的 Web 应用程序,并且不存在 Bootstrap。也不会有任何控制器或任何其他脚本文件。

现在选择 MVC 模板并单击确定。当 Visual Studio 创建此解决方案时,它将下载并安装到项目中的包之一将是 Bootstrap NuGet 包。您可以通过转到 packages.config 进行验证,您可以看到 Bootstrap 版本 3 包。

Bootstrap 版本 3 包

您还可以看到包含不同 css 文件的 Content 文件夹。

内容文件夹

运行此应用程序,您将看到以下页面。

运行这个应用程序

出现此页面时,您看到的大部分布局和样式都是 Bootstrap 应用的布局和样式。它包括顶部带有链接的导航栏以及为 ASP.NET 做广告的显示。它还包括所有这些关于入门和获得更多图书馆和网络托管的内容。

如果您稍微扩展浏览器,它们实际上会并排排列,这是 Bootstrap 响应式设计功能的一部分。

Bootstrap 的响应式设计功能

如果您查看内容文件夹,您将找到 Bootstrap.css 文件。

Bootstrap.css 文件

NuGet 包还提供了该文件的缩小版本,该版本更小一些。在脚本下,您将找到 Bootstrap.js,这是 Bootstrap 的某些组件所必需的。

Bootstrap.js

它确实依赖于 jQuery,幸运的是 jQuery 也安装在这个项目中,并且有一个 Bootstrap JavaScript 文件的缩小版本。

现在的问题是,所有这些都在应用程序中添加到哪里了?您可能会期望,它会在布局模板中,该项目的布局视图位于 View/Shared/_layout.cshtml 下。

布局视图控件

布局视图控制 UI 的结构。以下是 _layout.cshtml 文件中的完整代码。

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "utf-8" />
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
      <title>@ViewBag.Title - My ASP.NET Application</title>
      @Styles.Render("~/Content/css")
      @Scripts.Render("~/bundles/modernizr")
   </head>
	
   <body>
      <div class = "navbar navbar-inverse navbar-fixed-top">
         <div class = "container">
			
            <div class = "navbar-header">
               <button type = "button" class = "navbar-toggle" datatoggle =
                  "collapse" data-target = ".navbar-collapse">
                  <span class = "icon-bar"></span>
                  <span class = "icon-bar"></span>
                  <span class = "icon-bar"></span>
               </button>
					
               @Html.ActionLink("Application name", "Index", "Home", new
                  { area = "" }, new { @class = "navbar-brand" })
            </div>
				
            <div class = "navbar-collapse collapse">
               <ul class = "nav navbar-nav">
                  <li>@Html.ActionLink("Home", "Index", "Home")</li>
                  <li>@Html.ActionLink("About", "About", "Home")</li>
                  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
               </ul>
					
               @Html.Partial("_LoginPartial")
            </div>
				
         </div>
			
      </div>
      <div class = "container body-content">
         @RenderBody()
         <hr />
         <footer>
            <p>© @DateTime.Now.Year - My ASP.NET Application</p>
         </footer>
      </div>
		
      @Scripts.Render("~/bundles/jquery")
      @Scripts.Render("~/bundles/bootstrap")
      @RenderSection("scripts", required: false)
		
   </body>
</html>

在上面的代码中,有两点需要注意。首先在顶部,在 <title> 之后,您将看到以下代码行。

@Styles.Render("~/Content/css")

用于 Content/css 的 Styles.Render 实际上是将包含 Bootstrap.css 文件的位置,在底部,您将看到以下代码行。

@Scripts.Render("~/bundles/bootstrap")

它正在呈现 Bootstrap 脚本。因此,为了找出这些包中的确切内容,我们必须进入 App_Start 文件夹中的 BundleConfig 文件。

捆绑配置文件

在 BundleConfig 中,您可以在底部看到 CSS 包包括 Bootstrap.css 和我们自定义的 site.css。

bundles.Add(new StyleBundle("~/Content/css").Include(
   "~/Content/bootstrap.css",
   "~/Content/site.css"));

在这里,我们可以添加自己的样式表来自定义应用程序的外观。您还可以看到出现在包含 Bootstrap.js 和另一个 JavaScript 文件 response.js 的 CSS 包之前的 Bootstrap 包。

bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
   "~/Scripts/bootstrap.js",
   "~/Scripts/respond.js"));

让我们对 Bootstrap.css 进行注释,如以下代码所示。

bundles.Add(new StyleBundle("~/Content/css").Include(
   //"~/Content/bootstrap.css",
   "~/Content/site.css"));

再次运行此应用程序,只是为了让您了解 Bootstrap 正在做什么,因为现在唯一可用的样式是 site.css 中的样式。

site.css 中的样式

如您所见,我们丢失了布局,即页面顶部的导航栏。现在一切看起来都很普通和无聊。

现在让我们看看 Bootstrap 是什么。Bootstrap 可以自动完成一些事情,当您添加类并拥有正确的 HTML 结构时,Bootstrap 可以为您做一些事情。如果您查看 _layout.cshtml 文件,您将看到如下代码所示的导航栏类。

<div class = "navbar navbar-inverse navbar-fixed-top">
   <div class = "container">
	
      <div class = "navbar-header">
         <button type = "button" class = "navbar-toggle" datatoggle =
            "collapse" data-target = ".navbar-collapse">
            <span class = "icon-bar"></span>
            <span class = "icon-bar"></span>
            <span class = "icon-bar"></span>
         </button>
         <a class = "navbar-brand" href = "/">Application name</a>
      </div>
		
      <div class = "navbar-collapse collapse">
         <ul class = "nav navbar-nav">
            <li><a href = "/">Home</a></li>
            <li><a href = "/Home/About">About</a></li>
            <li><a href = "/Home/Contact">Contact</a></li>
         </ul>
			
         <ul class = "nav navbar-nav navbar-right">
            <li><a href = "/Account/Register" id = "registerLink">Register</a></li>
            <li><a href = "/Account/Login" id = "loginLink">Log in</a></li>
         </ul>
			
      </div>
		
   </div>
	
</div>

它是来自 Bootstrap 的 CSS 类,如导航栏、反向导航栏和固定顶部导航栏。如果您删除其中一些类(如 navbar inverse、navbar fixed top 并取消对 Bootstrap.css 的注释,然后再次运行您的应用程序,您将看到以下输出。

CSS 类

你会看到我们仍然有一个导航栏,但现在它没有使用反色,所以它是白色的。它也不会粘在页面的顶部。当您向下滚动时,导航栏会从顶部滚动,您将无法再看到它。

导航栏

ASP.NET MVC – 单元测试

在计算机编程中,单元测试是一种软件测试方法,通过它测试源代码的各个单元以确定它们是否适合使用。换句话说,它是一个软件开发过程,其中应用程序的最小可测试部分(称为单元)被单独和独立地检查以确保正常运行。

在过程编程中,一个单元可以是一个完整的模块,但更常见的是一个单独的函数或过程。在面向对象的编程中,一个单元通常是一个完整的接口,例如一个类,但也可以是一个单独的方法。

单元测试通常是自动化的,但也可以手动完成。

单元测试的目标

单元测试的主要目标是采用应用程序中最小的可测试软件,并确定它的行为是否完全符合您的预期。每个单元在将它们集成到模块中之前分别进行测试,以测试模块之间的接口。

让我们看一个简单的单元测试示例,在该示例中,我们使用单元测试创​​建了一个新的 ASP.NET MVC 应用程序。

步骤 1 – 打开 Visual Studio 并单击文件 → 新建 → 项目菜单选项。

一个新的项目对话框打开。

新建项目对话框

步骤 2 – 从左侧窗格中,选择模板 > Visual C# > Web。

步骤 3 – 在中间窗格中,选择 ASP.NET Web 应用程序。

第 4 步– 在名称字段中输入项目名称“MVCUnitTestingDemo”,然后单击“确定”继续。您将看到以下对话框,要求您设置 ASP.NET 项目的初始内容。

MVCUnitTestingDemo

第 5 步– 选择 MVC 作为模板,不要忘记选中对话框底部的添加单元测试复选框。您也可以更改测试项目名称,但在本示例中,我们将其保留原样,因为它是默认名称。

一旦 Visual Studio 创建了项目,您将在解决方案资源管理器窗口中看到许多文件和文件夹。

第 6 步– 您可以看到解决方案资源管理器中有两个项目。一个是 ASP.NET Web 项目,另一个是单元测试项目。

网络项目

步骤 7 – 运行此应用程序,您将看到以下输出。

运行网络项目

如上图所示,导航栏上有主页、关于和联系人按钮。让我们选择“关于”,您将看到以下视图。

关于选择

让我们选择联系人,然后弹出以下屏幕。

联系选择

现在让我们展开“MVCUnitTestingDemo”项目,您将在 Controllers 文件夹下看到 HomeController.cs 文件。

HomeController.cs 文件

HomeController 包含三个操作方法,如以下代码所示。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCUnitTestingDemo.Controllers {
   public class HomeController : Controller{
      public ActionResult Index(){
         return View();
      } 
		
      public ActionResult About(){
         ViewBag.Message = "Your application description page.";
         return View();
      }
		
      public ActionResult Contact(){
         ViewBag.Message = "Your contact page.";
         return View();
      }
   }
}

让我们展开MVCUnitTestingDemo.Tests项目,您将在 Controllers 文件夹下看到 HomeControllerTest.cs 文件。

MVCUnitTestingDemo.Test

在这个 HomeControllerTest 类中,您将看到三个方法,如以下代码所示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using MVCUnitTestingDemo;
using MVCUnitTestingDemo.Controllers;

namespace MVCUnitTestingDemo.Tests.Controllers{
   [TestClass]
   public class HomeControllerTest{
	
      [TestMethod]
      public void Index(){
         // Arrange
         HomeController controller = new HomeController();
         // Act
         ViewResult result = controller.Index() as ViewResult;
         // Assert
         Assert.IsNotNull(result);
      }
		
      [TestMethod]
      public void About(){
         // Arrange
         HomeController controller = new HomeController();
         // Act
         ViewResult result = controller.About() as ViewResult;
         // Assert
         Assert.AreEqual("Your application description page.", result.ViewBag.Message);
      }
		
      [TestMethod]
      public void Contact(){
         // Arrange
         HomeController controller = new HomeController();
         // Act
         ViewResult result = controller.Contact() as ViewResult;
         // Assert
         Assert.IsNotNull(result);
      }
   }
}

这三个方法将测试Index、About 和Contact 操作方法是否正常工作。要测试这三种操作方法,请转到“测试”菜单。

测试菜单

选择运行 → 所有测试来测试这些操作方法。

行动方法

现在您将在左侧看到测试资源管理器,您可以在其中看到所有测试均已通过。让我们再添加一个操作方法,它将列出所有员工。首先,我们需要在 Models 文件夹中添加一个员工类。

以下是 Employee 类的实现。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;

namespace MVCUnitTestingDemo.Models{
   public class Employee{
      public int ID { get; set; }
      public string Name { get; set; }
      public DateTime JoiningDate { get; set; }
      public int Age { get; set; }
   }
}

我们需要添加EmployeeController。右键单击解决方案资源管理器中的控制器文件夹,然后选择添加 → 控制器。

它将显示“添加脚手架”对话框。

添加脚手架

选择 MVC 5 Controller – Empty 选项并单击“添加”按钮,将出现“添加控制器”对话框。

将名称设置为 EmployeeController 并单击“添加”按钮。

添加控制器员工控制器

您将在 Controllers 文件夹中看到一个新的 C# 文件“EmployeeController.cs”,该文件已打开以在 Visual Studio 中进行编辑。让我们使用以下代码更新 EmployeeController。

using MVCUnitTestingDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCUnitTestingDemo.Controllers {
   public class EmployeeController : Controller{
      [NonAction]
		
      public List<Employee> GetEmployeeList(){
         return new List<Employee>{
            new Employee{
               ID = 1,
               Name = "Allan",
               JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
               Age = 23
            },
				
            new Employee{
               ID = 2,
               Name = "Carson",
               JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
               Age = 45
            },
				
            new Employee{
               ID = 3,
               Name = "Carson",
               JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
               Age = 37
            },
				
            new Employee{
               ID = 4,
               Name = "Laura",
               JoiningDate = DateTime.Parse(DateTime.Today.ToString()),
               Age = 26
            },
         };
      }
      
      // GET: Employee
      public ActionResult Index(){
         return View();
      }
		
      public ActionResult Employees(){
         var employees = from e in GetEmployeeList()
         orderby e.ID
         select e;
         return View(employees);
      }
   }
}

要为员工操作方法添加视图,请右键单击员工操作并选择添加视图…

员工行动

您将看到视图的默认名称。从模板下拉列表中选择“列表”,从模型类下拉列表中选择“员工”,然后单击确定。

现在我们需要添加链接员工列表,让我们打开 Views/Shared 文件夹下的 _layout.cshtml 文件,并在联系人链接下方添加员工列表的链接。

<li>@Html.ActionLink("Employees List", "Employees", "Employee")</li>

以下是_layout.cshtml 的完整实现。

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "utf-8" />
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
      <title>@ViewBag.Title - My ASP.NET Application</title>
      @Styles.Render("~/Content/css")
      @Scripts.Render("~/bundles/modernizr")
   </head>
	
   <body>
      <div class = "navbar navbar-inverse navbar-fixed-top">
         <div class = "container">
			
            <div class = "navbar-header">
               <button type = "button" class = "navbar-toggle" datatoggle =
                  "collapse" data-target = ".navbar-collapse">
                  <span class = "icon-bar"></span>
                  <span class = "icon-bar"></span>
                  <span class = "icon-bar"></span>
               </button>
					
               @Html.ActionLink("Application name", "Index", "Home", new
                  { area = "" }, new { @class = "navbar-brand" })
            </div>
				
            <div class = "navbar-collapse collapse">
               <ul class = "nav navbar-nav">
                  <li>@Html.ActionLink("Home", "Index", "Home")</li>
                  <li>@Html.ActionLink("About", "About", "Home")</li>
                  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                  <li>@Html.ActionLink("Employees List", "Employees", "Employee")</li>
               </ul>
					
               @Html.Partial("_LoginPartial")
            </div>
				
         </div>
			
      </div>
		
      <div class = "container body-content">
         @RenderBody()
         <hr />
         <footer>
            <p>© @DateTime.Now.Year - My ASP.NET Application</p>
         </footer>
      </div>
		
      @Scripts.Render("~/bundles/jquery")
      @Scripts.Render("~/bundles/bootstrap")
      @RenderSection("scripts", required: false)
		
   </body>
</html>

要从 Employee 控制器测试 Employees 操作方法,我们需要在单元测试项目中添加另一个测试方法。下面是 EmployeeControllerTest 类,我们将在其中测试 Employees 操作方法。

[TestClass]
public class EmployeeControllerTest{
   [TestMethod]
   public void Employees(){
      // Arrange
      EmployeeController controller = new EmployeeController();
		
      // Act
      ViewResult result = controller.Index() as ViewResult;
		
      // Assert
      Assert.IsNotNull(result);
   }
}

从测试菜单中选择运行 → 所有测试来测试这些操作方法。

员工测试方法

可以看到现在Employees测试方法也通过了。运行应用程序时,您将看到以下输出。

单击导航栏中的“员工列表”选项,您将看到员工列表。

员工名单

ASP.NET MVC – 部署

在本章中,我们将介绍如何部署 ASP.NET MVC 应用程序。在了解了 ASP.NET MVC 应用程序中的不同概念之后,现在是时候了解部署过程了。因此,每当我们构建任何 MVC 应用程序时,我们基本上都会生成一个与内部所有应用程序设置和逻辑相关联dll文件,这些dll位于项目的 bin 目录中,如下面的屏幕截图所示。

部署

发布到 Microsoft Azure

让我们看一个简单的例子,在这个例子中我们将把我们的例子部署到 Microsoft Azure。

步骤 1 – 右键单击​​解决方案资源管理器中的项目,然后选择发布,如下面的屏幕截图所示。

解决方案资源管理器

第 2 步– 您将看到“发布 Web”对话框。单击 Microsoft Azure Web 应用程序。

Microsoft Azure Web 应用程序

它将显示“登录”页面。

步骤 3 – 输入 Microsoft Azure 订阅的凭据。

证书

成功连接到 Azure 帐户后,您将看到以下对话框。

Azure 帐户

第 4 步– 单击“新建”按钮。

新按钮

步骤 5 – 在上述对话框中输入所需信息,例如 Web 应用程序名称,该名称必须是唯一的名称。您还需要输入应用服务计划、资源组,然后选择您所在的地区。

所需信息

步骤 6 – 单击“下一步”按钮继续。

单击下一步按钮

步骤 7 – 单击省略号“…”以选择连接字符串。

省略号

步骤 8 – 选择服务器名称,然后选择 Windows 身份验证选项。还要选择数据库名称。现在您将看到为您生成了连接字符串。

生成连接

步骤 9 – 单击“下一步”继续。

点击发布网页下一步

步骤 10 – 要检查我们将发布到 Azure 的所有文件和 dll,请单击开始预览。单击“发布”按钮发布您的应用程序。

应用程序成功发布到 Azure 后,您将在输出窗口中看到该消息。

发布 Azure

第 11 步– 现在打开浏览器并输入以下 URL “http://mymvcdemoapp.azurewebsites.net/employees”,您将看到员工列表。

员工名单

第 12 步– 现在,如果您转到 Azure 门户并单击“应用服务”,则会看到您的应用程序已部署到 Azure。

应用服务

第 13 步– 单击您的应用程序名称,您将看到与该应用程序相关的信息,例如 URL、状态、位置等。

相关信息

到目前为止,我们已经看到了如何在创建应用程序后将 Web 应用程序发布到 Azure 应用程序。您还可以创建一个应用程序,该应用程序将部署到 Azure。

让我们创建一个新的 ASP.NET MVC 应用程序。

ASP.NET MVC 应用程序

步骤 1 – 单击确定,您将看到以下对话框。

ASP.NET 项目

第 2 步– 选择 MVC 模板,并在云复选框中选中主机。单击确定。

当“配置 Microsoft Azure Web 应用设置”对话框出现时,请确保您已登录到 Azure。

配置 Microsoft Azure

您可以看到默认名称,但您也可以更改Web App name

步骤 3 – 输入所需的信息,如下面的屏幕截图所示。

输入所需信息

第 4 步– 从数据库服务器下拉列表中选择“创建新服务器”,您将看到附加字段。

创建新服务器

步骤 5 – 输入数据库服务器、用户名和密码。单击确定。

第 6 步– 创建项目后,运行应用程序,您将看到它正在本地主机上运行。

运行应用程序

第 7 步– 要将这些应用程序部署到 Azure,请右键单击解决方案资源管理器中的项目并选择“发布”。

部署应用程序

您将看到以下对话框。

选择发布目标

步骤 8 – 单击“Microsoft Azure Web 应用程序”。

单击 Microsoft Azure Web 应用程序

第 9 步– 从现有 Web 应用程序中选择您的应用程序名称,然后单击确定。

选择应用名称

步骤 10 – 单击“验证连接”按钮以检查 Azure 上的连接。

验证连接

步骤 11 – 单击“下一步”继续。

点击下一步

现在您将看到默认情况下已经生成了连接字符串。

生成的连接字符串

步骤 12 – 单击“下一步”继续。

下一个连接字符串

步骤 13 – 要检查将发布到 Azure 的所有文件和 dll,请单击“开始预览”。

预习

第 14 步– 单击“发布”按钮发布您的应用程序。应用程序成功发布到 Azure 后,您将在输出窗口中看到该消息。

发布按钮

您还将看到应用程序现在正在从云中运行。

云

让我们再次访问 Azure 门户。您也将在此处看到该应用程序。

Azure 门户

ASP.NET MVC – 自托管

在本章中,我们将介绍自托管。自托管为应用程序创建了一个运行时环境,可以在任何环境(例如 MAC 或 Linux 机器等)中运行。自托管还意味着它将具有迷你 CLR 版本。

使用文件系统部署

我们来看一个简单的自托管示例。

步骤 1 – 完成 ASP.NET MVC 应用程序并且您想使用自托管后,右键单击解决方案资源管理器中的项目。

使用自托管

您将看到以下对话框。

自托管对话框

步骤 2 – 单击“自定义”选项,将显示“新建自定义配置文件”对话框。

新建自定义配置文件对话框

步骤 3 – 输入配置文件名称并单击确定。

输入配置文件名称

步骤 4 – 从发布方法下拉列表中选择文件系统,并指定目标位置。单击“下一步”按钮。

选择文件系统

步骤 5 – 展开文件发布选项。

文件发布选项

第 6 步– 选中“发布前删除所有现有文件”和“发布期间预编译”复选框,然后单击“下一步”继续。

删除所有现有文件

步骤 7 – 单击“发布”按钮,它将在所需位置发布文件。

在所需位置发布文件

您将看到系统目标位置中的所有文件和文件夹。

目标位置

它将拥有在本地主机上部署所需的所有文件。

步骤 8 – 现在打开打开或关闭 Windows 功能并展开 Internet 信息服务 → 万维网服务 → 应用程序开发功能。

打开车窗功能

步骤 9 – 选中上面屏幕截图中显示的复选框,然后单击确定。

步骤 10 – 让我们打开 IIS 管理器,如下面的屏幕截图所示。

IIS 管理器

步骤 11 – 您将在屏幕左侧看到不同的连接,右键单击 MyWebSite。

不同的连接

步骤 12 – 选择“转换为应用程序”选项。

转换为应用程序

如您所见,它的物理路径与我们上面在发布时提到的相同,使用文件系统。

步骤 13 – 单击确定继续。

单击确定

现在您可以看到它的图标已更改。

步骤 14 – 打开浏览器并指定以下 URL http://localhost/MyWebSite

指定网址

您可以看到它正在从我们在部署期间指定的文件夹中运行。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁