65.9K
CodeProject 正在变化。 阅读更多。
Home

使用真实世界示例理解 ASP.NET MVC,适用于初级和中级程序员

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (35投票s)

2015年1月31日

MIT

24分钟阅读

viewsIcon

384399

downloadIcon

18944

本文简要描述和概述了 ASP.NET 的 MVC 框架,以及开发人员如何将其真实世界的对象转换为 MVC 框架,以创建 Web 应用程序。

引言

ASP.NET 为开发人员提供了一个新的网站开发框架,在该框架中,他们可以轻松区分数据层、业务层以及用于在屏幕上渲染这些对象的方法。他们将此框架称为 ASP.NET MVC,其中 MVC 代表 **M**odel(模型)、**V**iew(视图)、**C**ontroller(控制器)。我将在本博客文章中详细阐述这些项目以及我将使用的其他对象和技术。首先,让我们讨论一下 MVC 模式本身是什么,以及与 ASP.NET 的其他框架(包括众所周知的 Web Pages 和 Web Forms,以及所有其他 Web 脚本框架)相比,ASP.NET MVC 为我们提供了什么。

ASP.NET MVC

首先要理解 ASP.NET MVC 框架本身。一旦我们对 ASP.NET MVC 框架有了足够的了解,那么我们就能更容易地理解 ASP.NET 团队为什么为我们提供了这个框架。在 Web 开发中,有不同的方案用于创建网站和 Web 应用程序,在早期阶段这似乎不会引起问题。解决一个 bug 可能需要数小时的绞尽脑汁和一些其他帮助。找到脚本在 HTML 网页内部的问题更难。在这些场景中,将代码与数据和 HTML 标记分离总是很有帮助的。这将使查找和解决问题变得容易得多,因为现在所有的代码都已分离,在精确位置找到问题将不是一项困难的任务。这三个领域被划分并构成了 MVC;Web 开发的模型、视图和控制器模式。

实际上,这并非 Web 开发特有的模式。如果您访问维基百科关于此主题的页面,您会发现它实际上是用于软件开发的框架,这意味着它可以在任何您想要区分应用程序的数据链路层、业务逻辑层和渲染代码的地方应用。

MVC-Process.svg

MVC 模式中这三个对象之间的联系已在上面的图片中描绘。

控制器 (Controller)

MVC 中的控制器(Controller)排在最后,但它是 MVC 模式中使用最广泛的部分。它用于处理来自客户端的 HTTP 请求;这些请求可能来自浏览器或任何其他可以生成 `HttpRequest` 的应用程序(不要与 .NET 的 `HttpRequest` 对象混淆;而是一个简单的 HTTP `Request`)。每个请求到来时,都会由 `Controller` 处理,然后 `Controller` 根据请求决定加载数据、创建响应,然后将数据发送回客户端。

这里还需要注意,您的 Controller 作为 Model 和 View 之间的桥梁。因为它们本身无法执行任何操作。Controller 触发它们的事件并使它们执行一些操作,例如从 Model 返回数据,或从 View 渲染 HTML 文档等。所有资源和错误也由 Controller 处理,使其成为该模式的核心,因为响应也从 Controller 发送回来。您可以将 Controller 视为整个业务逻辑层的一个示例。用于运行应用程序后端处理的代码,例如创建账户、管理解决方案等,将构成此模式的 Controller 部分。

视图

接下来是视图(View)部分,这是实际显示给用户的网页。它包含作为对用户请求的响应而发送回数据的所有 HTML 代码。没错,Controller 将此响应发送回客户端,View 本身不将此响应发送给客户端,而是 Controller 获取此数据并将其发送回客户端。

视图也可以动态创建。如前所述,所有请求都由控制器处理,因此任何参数(包括 `QueryStrings`)也可以由控制器处理。使用这些参数,我们可以生成动态视图。因此,如果发送的数据不是我们自己的选择,我们的视图中的动态内容会改变它们的布局或显示一些其他错误消息。视图通常取决于用于创建视图的模型,这些动态数据对象是从模型中捕获的(模型将在下一节中讨论)。

这里需要注意的是,虽然“活动部分”是 View,但 Controller 仍在传递值和检索要发送给客户端的数据方面发挥着至关重要的作用。

模型

顾名思义,它是一个对象的模型。在这种情况下,对象是我们的应用程序数据。它可以是任何类型,例如从数据库中提取;无论是 SQL Server、MySQL 还是 MS Access 等,或者它可以是来自报告或电子表格等的简单数据。模型从不向用户(实际上是客户端)显示,因为他应该看到我们希望他看到的数据和结果,这就是为什么在模型和用户(客户端)之间保持一个很好的抽象层是一种好方法。

模型不仅存储数据,同时还会保持视图和控制器更新,或者对其进行的任何更改。模型的_设计_,就像控制器和视图的_设计_一样,只是为了在它们三者之间没有歧义,并且它们之间易于通信,以使 Web 应用程序流畅。每次发生更改时,视图都会由控制器更新,因为控制器会收到有关更改的通知(此通知事件也由控制器引发;正如我之前提到的,控制器处理事件)。为了在模型中存储任何内容,用户没有提供直接连接到模型的任何表单,而是由控制器在视图中为用户生成一个表单供其填写。一旦表单填写完毕,表单值就会传递给模型以进行存储。各种数据验证(其中最特殊的一种是 SQL 注入)可以在控制器级别进行检查,而不是丢失(重要)数据。

The user must be allowed to interact with Model himself, instead a Controller must be used to connect to the Model to get the data for the user's View that would be shown to him.

用户不得直接与模型交互,而必须使用控制器连接到模型,以获取要显示给用户的视图数据。

到目前为止,我们一直在讨论 ASP.NET MVC 本身。在下一节中,我们将讨论一个 ASP.NET MVC 应用程序的真实世界示例,我将展示如何创建自定义控制器、视图和模型。在 ASP.NET MVC 项目中,用户触发控制器,控制器然后读取并操作请求,向模型请求数据,获取数据,然后更新视图以发送回客户端。

Overview of MVC pattern.

MVC 模式概述

ASP.NET MVC 应用程序的真实世界示例

在本博文中,我将解释如何创建一个 MVC 应用程序来控制您客户的数据。为此,我将使用模型、视图和控制器架构,以便我可以轻松区分我的应用程序的数据(这将是客户的数据)、请求和响应的代码(这将构成控制器)以及数据如何显示给用户(我的应用程序的视图)。我将从头开始创建所有内容,以便让您理解一切。为此,我将从在我的应用程序中创建每个对象、每个控制器、每个视图和每个模型开始。

这里您应该考虑的一点是,我将使用 JSON 文件作为数据源,因为数据库字段已经由 ASP.NET 团队做得最好。我认为没有必要重写相同的东西,这就是为什么我将解释如何将_任何东西_用作_您的模型_。如果您想阅读该内容,并希望坚持使用 SQL Server 数据库,您可以访问 ASP.NET MVC 教程网站学习。您说得对,这里不支持 Entity Framework!这就是为什么我说我将从头开始创建所有内容,以便为您解释 MVC 模式的每一个细节,以及如何创建响应_实际流程_的动作,而不仅仅是内置动作。

现实生活示例

让我们举一个简单办公室的例子,一个工作人员接待不同的客户,其姓名、地址都已存储。为了区分所有客户,还存储了一个 ID。客户是否受信任也与客户信息一起存储。办公室经理希望能够创建新客户、修改现有客户,并且在完成对客户的处理后,他希望能够删除以前的客户。为了在 ASP.NET MVC 中实现这个基本示例,我们将从创建一个简单的 ASP.NET MVC 应用程序开始。为此,您可以按 CTRL+SHIFT+N,或者您可以单击“**文件**”,然后选择“**新建**”和“**项目**”。如下所示:

Creating a new project - in Visual Studio 2013

在 Visual Studio 2013 中创建新项目

之后,请选择 Web,并在其中选择 ASP.NET Web 应用程序,然后随心所欲地命名它。我将其命名为 `ASPNET_MVC_Application`。您可以使用任何您喜欢的名称。

Selecting an ASP.NET web application.

选择 ASP.NET Web 应用程序

然后,您需要在下一个选项卡中为您的应用程序进行选择。您暂时不应进行任何更改,保持所选选项,然后在此选项卡上单击“**下一步**”。

Screenshot (160)

这将创建您的应用程序,其中包含应用程序设置的默认内容。您可能会在 Visual Studio 中看到此网页。

ASP.NET MVC read me page viewed inside the Visual Studiom 2013 - application's first run.

在 Visual Studio 2013 中查看 ASP.NET MVC 自述页面 - 应用程序首次运行

这是直到应用程序创建完成的教程。此网页也是成功的标志,如果您仍想确保一切运行正常,只需按下绿色按钮(上面有浏览器名称;我的显示的是 Google Chrome)即可在浏览器中查看您的应用程序运行情况。在下一节中,我将创建应用程序的对象 (MVC),然后向您展示它们如何交互,最后,我将提供一些使您的应用程序更好的技巧。

自定义 ASP.NET MVC 应用程序

一切设置完毕,您的应用程序运行起来后。您可以继续对其进行更改,使其反映您自己的应用程序,而不是默认的 ASP.NET MVC 示例应用程序。首先要做的是创建一个控制器,我们将在应用程序中使用它来控制所有请求并发送回响应(视图)。如何创建视图以及模型是什么将在后面的章节中介绍。现在,只需专注于理解 MVC 中的控制器。

所需包:由于我们将使用 JSON 数据,Newtonsoft.Json 包是一个非常有用的包,因此在继续之前,打开您的 NuGet 包管理器控制台(在“**工具**”内部)并运行以下命令以下载并将其包含在您的项目中。_它是必需的。_

Install-Package Newtonsoft.Json

创建自定义控制器

自定义控制器是您可以用来为应用程序创建自定义控制器的东西,它将处理传入的请求,并向用户提供填充了模型数据的视图。您可以随意命名它们,没有约定;只有一个约定是将“`Controller`”附加到类的名称后面。`Controller` 实际上是一个继承自 `System.Web.Mvc.Controller` 类的类,它允许继承 `Controller`(父)类的所有函数和成员。让我们创建一个 `Controller`。在您的源代码中,有一个名为 _Controllers_ 的文件夹。如果您打开它,默认会有 3 个控制器,您可以创建自己的控制器。

Default controllers in ASP.NET MVC application

ASP.NET MVC 应用程序中的默认控制器

右键单击“Controller”文件夹,然后在“**添加**”选项中,单击“**Controller**”以创建一个新的控制器。

Creating a new Controller

创建新控制器

为您的控制器指定一个自定义名称;请记住在类的名称末尾加上 `Controller`。您必须创建一个空控制器,因为为了本文的目的,我们不会使用任何_内置_功能,而只使用从零开始的类。

Screenshot (170)

We just need an Empty controller, to create our own functions (actions in MVC) for it to handle and perform.

我们只需要一个空的控制器,来创建我们自己的函数(在 MVC 中称为动作)来处理和执行。

在此阶段,您的基本 `Controller` 已创建,您现在可以对其进行自定义。在我们继续创建此 `Controller` 将执行的动作之前,我想提醒您_Views_ 文件夹中发生的(自动)更改。_Views_ 文件夹是关于什么的,是的,_它_不言自明,但我们将在下一节中也会讨论它。现在,您的 _View_ 文件夹中有一个新的 `Client`(或您创建的任何 `Controller` 命名)文件夹。现在它开始有点意义了,不是吗?每个控制器都有其自己特定的视图来显示数据,每次请求从客户端(当然不是我们的类,而是用户)发起时,都会使用 `Controller`(您可以认为是创建了该类的一个实例),然后将根据(URL 内部)检查 `Controller` 的动作(这将触发 `Controller` 的函数,我们将在下一步创建)。像每个类一样,我们可以为我们的 `Controller` 创建不同的函数,这些函数称为动作。让我们思考一下我们应该让经理对客户做些什么。他希望:

  1. 创建新客户 – `Create`
  2. 修改当前客户数据 – `Update` 或 `Edit`
  3. 完成工作后删除客户 – `Delete`

我们可以使用上述逻辑为客户控制器创建我们的函数。打开您的 _ClientController.cs_ 文件并编辑它,写入以下代码。

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

using ASP.NET_MVC_Application.Models;
using Newtonsoft.Json;

namespace ASP.NET_MVC_Application.Controllers
{
   public class ClientController : Controller
   {
      // GET: Client
      public ActionResult Index()
      {
         // Load the data for the client
         var clients = Client.GetClients();

         // Return the view.
         return View(clients);
      }

      public ActionResult Create()
      {
         ViewBag.Submitted = false;
         var created = false;
         // Create the Client
         if (HttpContext.Request.RequestType == "POST")
         {
            ViewBag.Submitted = true;
            // If the request is POST, get the values from the form
            var id = Request.Form["id"];
            var name = Request.Form["name"];
            var address = Request.Form["address"];
            var trusted = false;
 
            if(Request.Form["trusted"] == "on") {
               trusted = true;
            }

            // Create a new Client for these details.
            Client client = new Client()
            {
               ID = Convert.ToInt16(id), 
               Name = name,
               Address = address,
               Trusted = Convert.ToBoolean(trusted)
            };

            // Save the client in the ClientList
            var ClientFile = Client.ClientFile;
            var ClientData = System.IO.File.ReadAllText(ClientFile);
            List<Client> ClientList = new List<Client>();
            ClientList = JsonConvert.DeserializeObject<List<Client>>(ClientData);

            if (ClientList == null)
            {
               ClientList = new List<Client>();
            }
            ClientList.Add(client);

            // Now save the list on the disk
            System.IO.File.WriteAllText(ClientFile, JsonConvert.SerializeObject(ClientList));

            // Denote that the client was created
            created = true;
         }

         if (created)
         {
            ViewBag.Message = "Client was created successfully.";
         }
         else
         {
            ViewBag.Message = "There was an error while creating the client.";
         }
       return View();
     }

     public ActionResult Update(int id)
     {
        if (HttpContext.Request.RequestType == "POST")
        {
           // Request is Post type; must be a submit
           var name = Request.Form["name"];
           var address = Request.Form["address"];
           var trusted = Request.Form["trusted"];

           // Get all of the clients
           var clints = Client.GetClients();

           foreach (Client client in clints)
           {
              // Find the client
              if (client.ID == id)
              {
                 // Client found, now update his properties and save it.
                 client.Name = name;
                 client.Address = address;
                 client.Trusted = Convert.ToBoolean(trusted);
                 // Break through the loop
                 break;
              }
           }

           // Update the clients in the disk
           System.IO.File.WriteAllText(Client.ClientFile, JsonConvert.SerializeObject(clints));

           // Add the details to the View
           Response.Redirect("~/Client/Index?Message=Client_Updated");
       }

       // Create a model object.
       var clnt = new Client();
       // Get the list of clients
       var clients = Client.GetClients();
       // Search within the clients
       foreach (Client client in clients)
       {
          // If the client's ID matches
          if (client.ID == id)
          {
              clnt = client; 
              // No need to further run the loop 
              break;
          }
       }
       if (clnt == null)
       {
           // No client was found
           ViewBag.Message = "No client was found.";
       }
     return View(clnt);
   }

   public ActionResult Delete(int id)
   {
      // Get the clients
      var Clients = Client.GetClients();
      var deleted = false;
      // Delete the specific one.
      foreach (Client client in Clients)
      {
        // Found the client
        if (client.ID == id)
        {
          // delete this client
          var index = Clients.IndexOf(client);
          Clients.RemoveAt(index);

          // Removed now save the data back.
          System.IO.File.WriteAllText(Client.ClientFile, JsonConvert.SerializeObject(Clients));
          deleted = true;
          break;
       }
    }

     // Add the process details to the ViewBag
     if (deleted)
     {
        ViewBag.Message = "Client was deleted successfully.";
     }
     else
     {
        ViewBag.Message = "There was an error while deleting the client.";
     }
     return View();
    }
  }
}

完成!那就是我们的控制器,如果你看一下上面的代码,你会发现一些函数、一些 `ViewBags` 和一些 `Views` 等。我会在最后解释它们,因为它们是 ASP.NET MVC 为应用程序提供的内置函数,我们必须使用它们才能使应用程序运行。每次你向应用程序发出请求以加载客户数据时,这个控制器都会采取行动,并提供用户(这里是你)想要从应用程序中获取的数据。在上面的代码中,`Create`、`Update`、`Delete` 和 `Index` 是类的函数,在 MVC 应用程序中,它们将充当应用程序 `Controller` 的动作。你将使用它们来告诉应用程序当用户触发应用程序中某个特定动作时该做什么。它们只是一个简单类中的普通函数;该类继承自 `System.Web.Mvc.Controller`。

创建自定义视图

后端代码(`Controller` 代码)完成后,您现在可以为应用程序创建视图。视图用于以 HTML 标记向客户端(用户)显示应用程序的内容(数据)。由于浏览器只能渲染 HTML 内容,我们将使用该标记,而视图就是为此目的而使用的。每个控制器都有其自己特定的视图。这里需要注意的一点是,要返回一个视图,视图的名称必须与动作的名称匹配。您可以这样理解,控制器中的每个动作(函数)都对应于应用程序中特定的视图(要返回的 HTML 文档)。我们需要四个视图,对应我们的四个动作:`Index`、`Create`、`Update`、`Delete`。要创建视图,您可以点击 _Views_ 文件夹,并创建一个新文件夹;但是请记住,这里您不需要创建任何新文件夹,因为正如我之前提到的,当您创建 `Controller` 时,已经创建了一个名为 `Controller` 名称“`Client`”的新文件夹。右键单击该文件夹,在 _Add_ 内部,单击“MVC 5 View with Layout”,然后点击“**下一步**”进入下一步。

Creating a new View (with Layout)

创建新视图(带布局)

现在命名 `View`,我将其命名为 `Index`,因为我们需要一个用于 Index 页面的视图。

Screenshot (172)

现在选择布局,布局应用于所有页面(`Views`)以使它们的设计相似。您也可以使用自己的视图,但为此,我将使用默认布局。

Screenshot (173)

这是使用 Visual Studio 在 ASP.NET MVC 中创建视图的分步方法。ASP.NET 使用 Razor 语法创建 HTML 页面,这缩短了开发人员的代码。更新此页面中的代码并编写以下代码:

@model IEnumerable<ASPNET_MVC_Application.Models.Client>

@{
   ViewBag.Title = "All Clients";
   Layout = "~/Views/Shared/_Layout.cshtml";
}

<h3>Following table shows the Clients detail</h3>
<p>You will find their details, as well as other links to other actions 
that can be performed and operated over the client objects. </p>

<p>You can also create a new client <a href="~/Client/Create">here</a>. </p>

<table class="clients-table">
   <tr>
   <th>ID</th>
   <th>Name</th>
   <th>Address</th>
   <th>Trusted</th>
   <th>Actions</th>
</tr>

 @if(Model != null && Model.Count() > 0)
 {
   foreach (var client in Model)
   {
     // Create the list of these clients
     <tr>
       <td>@client.ID</td>
       <td>@client.Name</td>
       <td>@client.Address</td>
       <td>@client.Trusted</td>
       <td>
         <a href="~/Client/Update/@client.ID">Update</a>
         <a href="~/Client/Delete/@client.ID">Delete</a>
       </td>
     </tr> 
   }
 }
</table>

在上面的页面源代码中,您会发现一个新事物。`@model IEnumerable<ASPNET_MVC_Application.Models.Client>`,这是此视图中要使用的数据类型;是的,它就是这里使用的模型。之后,它只是简单的 Razor 语法,用于创建 HTML 文档(视图)并返回给客户端(用户)。`Model` 对象(在 `foreach` 循环中使用的那个)拥有 `@model` 的任何传递值。

您应该自己创建接下来的三个视图(_作为测试_),并将此内容写入其中。

用于创建视图

@{
   ViewBag.Title = "Create";
   Layout = "~/Views/Shared/_Layout.cshtml";
}

<div>
   <h3>Fill in the following form</h3>
</div>
<form method="post" style="margin: 5% 0 0">
   <div class="float-left">
     <p>Client ID</p>
     <p>Name</p>
     <p>Address</p>
     <p>Trusted</p>
   </div>
   <div class="float-right">
     <input type="text" style="margin: 1px 0 2px" name="id" /><br />
     <input type="text" style="margin: 1px 0 2px" name="name" /><br />
     <input type="text" style="margin: 1px 0 2px" name="address" /><br />
     <input type="checkbox" style="margin: 1px 0 2px" name="trusted" /><br />
     <input type="submit" value="Save" />
   </div>
</form>

<p>
   @if (ViewBag.Submitted)
   {
     // If the form was submitted
     @ViewBag.Message
   }
</p>

用于更新视图

@model ASP.NET_MVC_Application.Models.Client

@{
   ViewBag.Title = "Update the Client";
   Layout = "~/Views/Shared/_Layout.cshtml";
}

<div>
  <h3>Update the following form</h3>
</div>
<form method="post" style="margin: 5% 0 0">
  <div class="float-left">
     <p>Name</p>
     <p>Address</p>
     <p>Trusted</p>
  </div>
  <div class="float-right">
     <input type="text" style="margin: 1px 0 2px" 
     name="name" value="@Model.Name" /><br />
     <input type="text" style="margin: 1px 0 2px" 
     name="address" value="@Model.Address" /><br />
     <input type="checkbox" style="margin: 1px 0 2px" name="trusted" 
          @if (Model.Trusted) { <text>checked="checked"</text> } 
     />
 <br />
     <input type="submit" value="Save" />
  </div>
</form>

<p>
   @if (ViewBag.Submitted != null && ViewBag.Submitted)
   {
      // If the form was submitted
     @ViewBag.Message
   }
</p>

用于删除视图

@{
   Layout = "~/Views/Shared/_Layout.cshtml";
}

<p>@ViewBag.Message</p>

您会发现,在创建视图中,我没有传递任何模型。这是因为,对于视图来说,拥有模型并非强制。模型只是为了允许动态内容,如果您不想使用任何模型,那很好,您不必在每个视图中都使用模型来创建 MVC 应用程序。这些只是简单的 HTML 页面,通过 Razor 语法更新内容,然后以 HTML 标记的形式发送回浏览器,用于渲染。_ViewStart.cshtml_ 页面用作检查任何布局的第一个页面。如果您不想为所有页面本身设置任何布局,并希望在整个 Web 应用程序中拥有独特的外观,您可以在此页面中进行设置,它将应用于所有页面。

创建自定义模型

就模型而言,ASP.NET MVC 允许您使用任何类型的数据(来自数据源;服务器或其他)作为模型。您可以将数据从模型通过控制器传递到视图,然后视图将作为简单的 HTML 标记渲染,并在浏览器中显示给用户。

我已经提到过,如果您错过了上面提到的一点,如果您想将 SQL Server 数据库用作应用程序的模型,那么 ASP.NET 团队已经为此提供了一个非常好的教程,您可能希望在此处加入他们的旅程。他们使用了 Entity Framework 来执行他们的操作。在我们的项目中,我们将使用 JSON 文件和自定义创建的操作来执行 CRUD 操作。这将(尝试)消除我们对这个 MVC 模式及其对其他技术和框架的广泛性的歧义。

一个 `Model`,就像一个 `Controller`,只是一个类文件,当处理来自客户端的请求时,我们可以实例化它并从中获取不同的对象。一个模型是我们自己语境中真实世界对象的表示;这里就是 ASP.NET MVC 应用程序。把它想象成有一个 `Client` 模型。它将有一个 `ClientID`、`Name`、`Address` 和一个 Trusted 作为标志(如果您不知道这些是从哪里来的,您应该回顾一下我们的场景)。您会为这个 Client 编写什么样的类?看看下面的类代码,了解我们将要拥有的 `Model`。

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

using Newtonsoft.Json;

namespace ASP.NET_MVC_Application.Models
{
   public class Client
   {
     public static string ClientFile = HttpContext.Current.Server.MapPath("~/App_Data/Clients.json");

     public int ID { get; set; }
     public string Name { get; set; }
     public string Address { get; set; }
     public bool Trusted { get; set; }

     public static List<Client> GetClients()
     {
        List<Client> clients = new List<Client>();
        if (File.Exists(ClientFile))
        {
           // File exists..
           string content = File.ReadAllText(ClientFile);
           // Deserialize the objects 
           clients = JsonConvert.DeserializeObject<List<Client>>(content);

           // Returns the clients, either empty list or containing the Client(s).
           return clients;
        }
        else
        {
           // Create the file 
           File.Create(ClientFile).Close();
           // Write data to it; [] means an array, 
           // List<Client> would throw error if [] is not wrapping text
           File.WriteAllText(ClientFile, "[]");

           // Re run the function
           GetClients();
        }

        return clients;
      }
   }
}

一个简单的 C# 类文件,它将作为我们应用程序的 `Model`。您会发现另一个主要变化,即此类的命名空间。名称在项目名称后附加了 `.Models`。这构成了我们不同的字段。ASP.NET 和 Visual Studio 为我们做了这些事情,尽管它们不是必需的,而只是要遵循的约定。让我们为我们的应用程序创建一个 `Model`,点击应用程序中的 _Models_ 文件夹,然后在“**添加**”中点击 `Class` 文件并将其命名为 _Client.cs_,然后点击“**下一步**”继续。

Select a new class file to be created as a Model

选择一个要创建为模型的新类文件

Screenshot (175)

随意命名,但我会使用 Client。

这些是 MVC 中用于创建应用程序的三个主要字段。但是,还有一些其他的次要字段可以工作并运行我们的应用程序,我将在这里为您介绍,以便您至少知道如何启动您的项目。

到目前为止,我们已经介绍了什么是 Controller(控制传入或传出客户端的 HTTP 请求),什么是 View(它在浏览器中呈现为 HTML 输出,返回给客户端的 HTML 标记响应可以称为 View),最后什么是 Model(我们应用程序中真实世界数据的表示称为模型)。现在,我们可以去看看运行我们应用程序的类和对象。像所有其他在 .NET 框架上运行的应用程序一样,ASP.NET 也向其开发人员公开了一些函数,用于在应用程序启动、应用程序崩溃等情况下执行不同的操作。如果您打开应用程序中的 _App_Start_ 文件夹,您会在那里找到一些类。`BundleConfig` 用于配置您的 JavaScript 库,ASP.NET 还使开发人员能够执行一些客户端操作。`IdentityConfig` 配置身份服务(用户授权服务),但我想在这里谈论的主要文件,也需要我们关注的是 _RouteConfig.cs_ 文件。

在 ASP.NET 中,您不需要固定物理路径,以便客户端将其请求发送到其虚拟位置进行读取。相反,您现在可以创建自定义 URL,让用户访问您的应用程序,而无需在该位置拥有指定文件。您创建不同的路由技术,允许 URL 中的不同数据值创建动态网页,以供客户端使用。

如果您打开此文件,您会在其中找到以下代码(我将使用文件的一部分)

routes.MapRoute(
   name: "Default",
   url: "{controller}/{action}/{id}",
   defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

这为您的应用程序定义了一条路由。它被命名为“`Default`”,并具有 URL 的默认配置,任何传入的 URL 都将与此方案匹配。第一个值将匹配 `Controller`,第二个匹配操作(`Controller` 类中的函数),然后是一个可选字段(参见默认值字段)。您可以更改这种排列顺序,以确保 URL 对您的上下文而言是网站和用户友好的。

每个 ASP.NET 应用程序都可以启用任意数量的路由,但只会使用最合适的路由,但至少必须存在一个路由才能使应用程序运行。现在让我们运行应用程序并测试,看看是否有任何需要我们注意的地方。

运行应用程序(可选部分;如果您想下载并测试应用程序,请跳过此部分)

这个应用程序是在名为“`ASP.NET MVC Application`”的应用程序上运行的,但我创建了一个名为“`ASPNET_MVC_Application`”的新应用程序,这两个之间有很大的不同,通常唯一的区别是命名空间命名,所以如果你一直在关注这篇博文,你可能会觉得有点困惑;对此我深表歉意。:)

In the beginning, the table is empty.

最初,表格是空的。

现在让我们开始添加一些对象;在此实例中,我们只考虑一个对象。

Fill in this form and click Save, the application would save this client's information.

填写此表单并点击保存,应用程序将保存此客户的信息。

Message showing the success of our operation.

显示操作成功的消息

如果您回到 `Client` 目录(控制器)的主页,您会发现那里有一个记录。

Screenshot (149)

现在让我们尝试更新此客户端的值,在表格的 Actions 属性中,您会找到两个超链接,它们实际上只是我们控制器的 Actions(函数),我们将把客户端的(可选)ID 传递给它,然后我们将更新值。我们将更新我们的值为:

Screenshot (151)

我们回去看看我们的视图现在是否有所改变。

Screenshot (152)

瞧!它确实反映了我们的更改,这证明了模型会更新视图以反映我们所做的任何新更改。尝试使用第二个超链接,它将从集合中删除该对象。

Screenshot (153)

这就是工作流程。现在我们的应用程序运行良好,我们的经理可以根据自己的要求添加、删除或修改客户数据。到目前为止,这个应用程序正在运行,我们的客户可以根据需要访问和使用它。

这是 ASP.NET MVC 应用程序的基本概述,它包含我们的数据模型、用户访问和查看的视图以及控制传入或传出客户端的 HTTP 数据控制器。

关注点

ASP.NET MVC 模式包含一个控制器,用于控制所有传入的 HTTP 请求和发往客户端的响应。一个视图用于生成 HTML 网页,Razor 视图引擎用于从 C# 对象创建 HTML 标记。一个 `Model` 是一个简单的 C# 类,它包含对象的属性。每次应用程序运行时,`Controller` 从 `Model` 获取数据,并填充 View,供用户在其浏览器中阅读结果。

每个真实世界的对象都可以在 ASP.NET MVC 应用程序中用作数据源。要创建模型,可以使用 C# 文件(如果您使用 C#,否则您将创建与您的语言相关的文件)。属性和成员充当您将在 HTML 标记中用于渲染的属性。

您可以通过创建路由技术来控制应用程序中使用的 URL 类型。这些定义了应用程序 URL 的结构。您的应用程序必须至少定义一条路由才能运行,否则您可以定义任意数量的路由。

MVC 模式消除了数据与应用程序后台代码之间的歧义。您的后台代码现在是应用程序控制器的一部分,并写在控制器内部。数据存储在模型中(实际上只是数据的表示,实际数据存储在文件或数据库等地方),用户看到的内容写在视图中。通过这种方式,可以尽快修复任何错误,而无需担心任何其他错误,因为现在每个字段都在不同的部分进行控制和编写。

该模式的模型部分绝不能执行任何业务逻辑,因为那将完全扼杀 MVC 模式的实际目的。这就是为什么所有逻辑代码都写在控制器中;甚至数据的创建或操作也应该通过函数在控制器中完成,因为用户与模型没有连接,这提供了一个额外的安全层,因为用户完全不了解数据库的 schema。将模型传递给视图时,您必须确保从控制器传递给视图的模型类型必须与从视图中提取的模型类型匹配。

`ViewBag` 和 `View` 是 ASP.NET 中用于操作 `View`(HTML 标记)的特殊对象,您可以将任何成员(动态的)从 `Controller` 传递到此 `ViewBag`,以在 `View` 页面(在本例中为 _.cshtml_)内部用于渲染;就像我用来显示错误或成功消息一样。

© . All rights reserved.