迭代 1 – 创建应用程序 (C#)

Microsoft

下载代码

在第一次迭代中,我们将以最简单的方式创建联系人管理器。 添加了对基本数据库操作的支持:创建、读取、更新和删除 (CRUD) 。

生成联系人管理 ASP.NET MVC 应用程序 (VB)

在本系列教程中,我们将从头到尾构建整个联系人管理应用程序。 通过 Contact Manager 应用程序,可以存储联系人列表的联系人信息(姓名、电话号码和电子邮件地址)。

我们通过多次迭代生成应用程序。 每次迭代后,我们都会逐步改进应用程序。 此多迭代方法的目标是使你能够了解每次更改的原因。

  • 迭代 #1 - 创建应用程序。 在第一次迭代中,我们将以最简单的方式创建联系人管理器。 添加了对基本数据库操作的支持:创建、读取、更新和删除 (CRUD) 。

  • 迭代 #2 - 使应用程序外观美观。 在此迭代中,我们通过修改默认 ASP.NET MVC 视图母版页和级联样式表来改进应用程序的外观。

  • 迭代 #3 - 添加表单验证。 在第三次迭代中,我们添加了基本表单验证。 我们会阻止用户在未填写必填表单字段的情况下提交表单。 我们还验证电子邮件地址和电话号码。

  • 迭代 #4 - 使应用程序松散耦合。 在第四次迭代中,我们将利用多种软件设计模式,以便更轻松地维护和修改 Contact Manager 应用程序。 例如,我们将应用程序重构为使用存储库模式和依赖关系注入模式。

  • 迭代 #5 - 创建单元测试。 在第五次迭代中,我们通过添加单元测试使应用程序更易于维护和修改。 我们将模拟数据模型类,并为控制器和验证逻辑生成单元测试。

  • 迭代 #6 - 使用测试驱动开发。 在第六次迭代中,我们通过先编写单元测试,然后针对单元测试编写代码,向应用程序添加新功能。 在此迭代中,我们将添加联系人组。

  • 迭代 #7 - 添加 Ajax 功能。 在第七次迭代中,我们通过添加对 Ajax 的支持来提高应用程序的响应能力和性能。

此迭代

在第一次迭代中,我们将生成基本应用程序。 目标是以尽可能快、最简单的方式构建 Contact Manager。 在以后的迭代中,我们将改进应用程序的设计。

Contact Manager 应用程序是一个基本的数据库驱动应用程序。 可以使用该应用程序创建新联系人、编辑现有联系人和删除联系人。

在此迭代中,我们将完成以下步骤:

  1. ASP.NET MVC 应用程序
  2. 创建用于存储联系人的数据库
  3. 使用 Microsoft 实体框架为数据库生成模型类
  4. 创建控制器操作和视图,使我们能够列出数据库中的所有联系人
  5. 创建控制器操作和视图,使我们能够在数据库中创建新联系人
  6. 创建控制器操作和视图,以便编辑数据库中的现有联系人
  7. 创建控制器操作和视图,以便删除数据库中的现有联系人

必备软件

在 ASP.NET MVC 应用程序中,必须在计算机上安装 Visual Studio 2008 或 Visual Web Developer 2008, (Visual Web Developer 是 Visual Studio 的免费版本,不包括 Visual Studio) 的所有高级功能。 可以从以下地址下载 Visual Studio 2008 试用版或 Visual Web Developer:

https://www.asp.net/downloads/essential/

注意

对于使用 Visual Web Developer ASP.NET MVC 应用程序,必须安装 Visual Web Developer Service Pack 1。 如果没有 Service Pack 1,则无法创建 Web 应用程序项目。

ASP.NET MVC 框架。 可以从以下地址下载 ASP.NET MVC 框架:

https://www.asp.net/mvc

在本教程中,我们使用 Microsoft Entity Framework 访问数据库。 实体框架包含在 .NET Framework 3.5 Service Pack 1 中。 可以从以下位置下载此 Service Pack:

https://www.microsoft.com/download/details.aspx?id=22&desc=dotnet35

作为逐个执行每个下载的替代方法,可以利用 Web 平台安装程序 (Web PI) 。 可以从以下地址下载 Web PI:

https://www.asp.net/downloads/essential/

ASP.NET MVC 项目

ASP.NET MVC Web 应用程序项目。 启动 Visual Studio 并选择菜单选项 “文件”、“新建项目”。 此时会显示“ 新建项目 ”对话框 (见图 1) 。 选择 “Web 项目类型”和 “ASP.NET MVC Web 应用程序 ”模板。 将新项目命名为 ContactManager ,然后单击“确定”按钮。

确保已从“新建项目”对话框右上角的下拉列表中选择.NET Framework 3.5。 否则,不会显示 ASP.NET MVC Web 应用程序模板。

屏幕截图显示了“新建项目”对话框,其中选择了“ASP.NET MVC Web 应用程序”。

图 01:“新建项目”对话框 (单击以查看全尺寸图像)

ASP.NET MVC 应用程序中,将显示“ 创建单元测试项目 ”对话框。 可以使用此对话框指示在创建 ASP.NET MVC 应用程序时,要创建单元测试项目并将其添加到解决方案。 尽管我们不会在此迭代中生成单元测试,但应选择选项 “是,创建单元测试项目 ”,因为我们计划在以后的迭代中添加单元测试。 在首次创建新 ASP.NET MVC 项目时添加测试项目比在创建 ASP.NET MVC 项目后添加测试项目要容易得多。

注意

由于 Visual Web Developer 不支持测试项目,因此在使用 Visual Web Developer 时,不会显示“创建单元测试项目”对话框。

屏幕截图显示“创建单元测试项目”对话框。

图 02:“创建单元测试项目”对话框 (单击以查看全尺寸图像)

ASP.NET MVC 应用程序显示在 Visual Studio 解决方案资源管理器 窗口中, (请参阅图 3) 。 如果看不到“解决方案资源管理器”窗口,则可以通过选择菜单选项“查看”、“解决方案资源管理器”来打开此窗口。 请注意,解决方案包含两个项目:ASP.NET MVC 项目和测试项目。 ASP.NET MVC 项目名为 ContactManager,测试项目名为 ContactManager.Tests。

显示解决方案资源管理器窗口的屏幕截图。

图 03:解决方案资源管理器窗口 (单击以查看全尺寸图像)

删除项目示例文件

ASP.NET MVC 项目模板包含控制器和视图的示例文件。 在创建新的 ASP.NET MVC 应用程序之前,应删除这些文件。 可以通过右键单击文件或文件夹并选择菜单选项“删除”,在解决方案资源管理器窗口中删除文件和文件夹。

需要从 ASP.NET MVC 项目中删除以下文件:

  • \Controllers\HomeController.cs

  • \Views\Home\About.aspx

  • \Views\Home\Index.aspx

并且,需要从测试项目中删除以下文件:

\Controllers\HomeControllerTest.cs

创建数据库

Contact Manager 应用程序是数据库驱动的 Web 应用程序。 我们使用数据库来存储联系人信息。

ASP.NET MVC 框架,其中包含任何新式数据库,包括 Microsoft SQL Server、Oracle、MySQL 和 IBM DB2 数据库。 在本教程中,我们使用 Microsoft SQL Server 数据库。 安装 Visual Studio 时,系统会提供安装 Microsoft SQL Server Express这是 Microsoft SQL Server 数据库的免费版本。

在解决方案资源管理器窗口中右键单击App_Data文件夹,然后选择菜单选项“添加”、“新建项”,以创建新数据库。 在“添加新项”对话框中,选择“数据”类别和“SQL Server数据库”模板 (请参阅图 4) 。 将新数据库命名为ContactManagerDB.mdf,然后单击“确定”按钮。

显示创建新的 Microsoft Sequel Server Express 数据库的屏幕截图。

图 04:创建新的Microsoft SQL Server Express数据库 (单击以查看全尺寸图像)

创建新数据库后,数据库将显示在解决方案资源管理器窗口中App_Data文件夹中。 双击ContactManager.mdf文件以打开“服务器资源管理器”窗口并连接到数据库。

注意

对于 Microsoft Visual Web Developer,“服务器资源管理器”窗口称为“数据库资源管理器”窗口。

可以使用“服务器资源管理器”窗口创建新的数据库对象,例如数据库表、视图、触发器和存储过程。 右键单击“表”文件夹,然后选择菜单选项 “添加新表”。 此时会显示数据库表Designer (见图 5) 。

显示数据库表Designer的屏幕截图。

图 05:数据库表Designer (单击以查看全尺寸图像)

我们需要创建包含以下列的表:

列名称 数据类型 允许 Null 值
ID int false
FirstName nvarchar(50) false
LastName nvarchar(50) false
电话 nvarchar(50) false
电子邮件 nvarchar(255) false

第一列 Id 列是特殊列。 需要将“Id”列标记为“标识”列和“主键”列。 通过展开“列属性” (查看图 6 的底部) 并向下滚动到“标识规范”属性来指示列是“标识”列。 将 (Is Identity) 属性设置为值 Yes

可以通过选择列并单击带有键图标的按钮,将列标记为“主键”列。 将列标记为“主键”列后,列旁边会显示一个键图标 (见图 6) 。

创建完表后,单击“保存”按钮 (带有软盘) 图标的按钮以保存新表。 为新表命名 联系人

创建完“联系人”数据库表后,应向该表添加一些记录。 右键单击“服务器资源管理器”窗口中的“联系人”表,然后选择菜单选项 “显示表数据”。 在显示的网格中输入一个或多个联系人。

创建数据模型

ASP.NET MVC 应用程序由模型、视图和控制器组成。 我们首先创建一个 Model 类,该类代表我们在上一部分中创建的 Contacts 表。

在本教程中,我们使用 Microsoft Entity Framework 从数据库自动生成模型类。

注意

ASP.NET MVC 框架不以任何方式绑定到 Microsoft 实体框架。 可以将 ASP.NET MVC 与 NHibernate、LINQ to SQL 或 ADO.NET 等替代数据库访问技术配合使用。

按照以下步骤创建数据模型类:

  1. 右键单击“解决方案资源管理器”窗口中的“模型”文件夹,然后选择“添加”、“新建项”。 此时会显示“ 添加新项 ”对话框 (见图 6) 。
  2. 选择 “数据 ”类别和 “ADO.NET 实体数据模型” 模板。 将数据模型命名为 ContactManagerModel.edmx ,然后单击“ 添加 ”按钮。 此时会显示“实体数据模型”向导 (见图 7) 。
  3. “选择模型内容 ”步骤中,选择“ 从数据库生成 ” (请参阅图 7) 。
  4. “选择数据连接 ”步骤中,选择ContactManagerDB.mdf数据库,并为“实体连接设置”输入名称 ContactManagerDBEntities (请参阅图 8) 。
  5. “选择数据库对象” 步骤中,选中标记为“表”的复选框 (请参阅图 9) 。 数据模型将包含数据库中包含的所有表, (只有一个表,即“联系人”表) 。 输入命名空间 Models。 单击“完成”按钮以完成向导。

屏幕截图显示“添加新项”对话框。

图 06:“添加新项”对话框 (单击以查看全尺寸图像)

屏幕截图显示选择“选择模型内容”。

图 07:选择“模型内容” (单击以查看全尺寸图像)

显示选择“选择数据连接”的屏幕截图。

图 08:选择“数据连接” (单击以查看全尺寸图像)

屏幕截图显示选择“选择数据库对象”。

图 09:选择数据库对象 (单击以查看全尺寸图像)

完成实体数据模型向导后,将显示实体数据模型Designer。 设计器显示一个类,该类对应于要建模的每个表。 应会看到一个名为 Contacts 的类。

实体数据模型向导基于数据库表名称生成类名称。 你几乎总是需要更改向导生成的类的名称。 右键单击设计器中的“联系人”类,然后选择菜单选项“ 重命名”。 将类的名称从 Contacts (plural) 更改为 Contact (单数) 。 更改类名称后,类应如图 10 所示。

屏幕截图显示 Contact 类。

图 10:Contact 类 (单击以查看全尺寸图像)

此时,我们已创建了数据库模型。 可以使用 Contact 类来表示数据库中的特定联系人记录。

创建主控制器

下一步是创建主控制器。 主控制器是在 ASP.NET MVC 应用程序中调用的默认控制器。

通过右键单击解决方案资源管理器窗口中的 Controllers 文件夹并选择菜单选项“添加”、“控制器 (请参阅图 11) ,创建主控制器类。 请注意标记为 “为创建、更新和详细信息方案添加操作方法”的复选框。 单击“ 添加 ”按钮之前,请确保选中此复选框。

显示添加主控制器的屏幕截图。

图 11:添加主控制器 (单击以查看全尺寸图像)

创建主控制器时,将获取清单 1 中的 类。

列表 1 - Controllers\HomeController.cs

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

namespace ContactManager.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

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

        //
        // GET: /Home/Details/5

        public ActionResult Details(int id)
        {
            return View();
        }

        //
        // GET: /Home/Create

        public ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /Home/Create

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                // TODO: Add insert logic here

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        //
        // GET: /Home/Edit/5
 
        public ActionResult Edit(int id)
        {
            return View();
        }

        //
        // POST: /Home/Edit/5

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add update logic here
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
}

列出联系人

为了在“联系人”数据库表中显示记录,我们需要创建“索引 () ”操作和“索引”视图。

主控制器已包含索引 () 操作。 我们需要修改此方法,使其看起来像清单 2。

清单 2 - Controllers\HomeController.cs

public class HomeController : Controller
{

    private ContactManagerDBEntities _entities = new ContactManagerDBEntities();

    //
    // GET: /Home/

    public ActionResult Index()
    {
        return View(_entities.ContactSet.ToList());
    }
…

请注意,清单 2 中的主控制器类包含名为 _entities 的私有字段。 _entities字段表示数据模型中的实体。 我们使用 _entities 字段与数据库进行通信。

Index () 方法返回一个视图,该视图代表联系人数据库表中的所有联系人。 表达式_entities。ContactSet.ToList () 将联系人列表作为泛型列表返回。

创建索引控制器后,接下来需要创建索引视图。 在创建索引视图之前,通过选择菜单选项 “生成”、“生成解决方案”来编译应用程序。 在添加视图之前,应始终编译项目,以便模型类列表显示在“ 添加视图 ”对话框中。

通过右键单击 Index () 方法并选择菜单选项 “添加视图 ” (请参阅图 12) ,创建索引视图。 选择此菜单选项将打开 “添加视图 ”对话框, (请参阅图 13) 。

显示添加“索引”视图的屏幕截图。

图 12:添加索引视图 (单击以查看全尺寸图像)

“添加视图”对话框中,检查标记为“创建强类型视图”的复选框。 选择“视图数据”类 ContactManager.Models.Contact 和“查看内容列表”。 选择这些选项将生成一个显示联系人记录列表的视图。

屏幕截图显示“添加视图”对话框。

图 13:“添加视图”对话框 (单击以查看全尺寸图像)

单击“ 添加” 按钮时,将生成清单 3 中的“索引”视图。 <请注意文件顶部显示的 %@ Page %> 指令。 索引视图继承自 ViewPage<IEnumerable<ContactManager.Models.Contact>> 类。 换句话说,视图中的 Model 类表示 Contact 实体的列表。

索引视图的主体包含一个 foreach 循环,循环访问 Model 类表示的每个触点。 Contact 类的每个属性的值都显示在 HTML 表中。

清单 3 - Views\Home\Index.aspx (未修改)

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<ContactManager.Models.Contact>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Index</h2>

    <table>
        <tr>
            <th></th>
            <th>
                Id
            </th>
            <th>
                FirstName
            </th>
            <th>
                LastName
            </th>
            <th>
                Phone
            </th>
            <th>
                Email
            </th>
        </tr>

    <% foreach (var item in Model) { %>
    
        <tr>
            <td>
                <%= Html.ActionLink("Edit", "Edit", new { id=item.Id  }) %> |
                <%= Html.ActionLink("Details", "Details", new { id=item.Id  })%>
            </td>
            <td>
                <%= Html.Encode(item.Id) %>
            </td>
            <td>
                <%= Html.Encode(item.FirstName) %>
            </td>
            <td>
                <%= Html.Encode(item.LastName) %>
            </td>
            <td>
                <%= Html.Encode(item.Phone) %>
            </td>
            <td>
                <%= Html.Encode(item.Email) %>
            </td>
        </tr>
    
    <% } %>

    </table>

    <p>
        <%= Html.ActionLink("Create New", "Create") %>
    </p>

</asp:Content>

我们需要对索引视图进行一次修改。 由于未创建“详细信息”视图,因此可以删除“详细信息”链接。 从“索引”视图中查找并删除以下代码:

{ id=item.Id }) %>

修改索引视图后,可以运行 Contact Manager 应用程序。 选择菜单选项“调试”、“开始调试”或直接按 F5。 首次运行应用程序时,你将获得图 14 中的对话框。 选择选项 “修改 Web.config 文件以启用调试 ”,然后单击“确定”按钮。

显示启用调试的屏幕截图。

图 14:启用调试 (单击以查看全尺寸图像)

默认情况下返回“索引”视图。 此视图列出联系人数据库表中的所有数据 (请参阅图 15) 。

屏幕截图显示了“索引”视图。

图 15:“索引”视图 (单击以查看全尺寸图像)

请注意,“索引”视图在视图底部包含标记为“新建”的链接。 在下一部分中,你将了解如何创建新联系人。

创建新联系人

若要使用户能够创建新联系人,我们需要将两个“创建 () ”操作添加到主控制器。 我们需要创建一个 Create () 操作,该操作返回用于创建新联系人的 HTML 表单。 我们需要创建第二个 Create () 操作来执行新联系人的实际数据库插入。

需要添加到主控制器的新 Create () 方法包含在清单 4 中。

列表 4 - Controllers\HomeController.cs (with Create methods)

//
// GET: /Home/Create

public ActionResult Create()
{
    return View();
} 

//
// POST: /Home/Create

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
    if (!ModelState.IsValid)
        return View();

    try
    {
        _entities.AddToContactSet(contactToCreate);
        _entities.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

第一个 Create () 方法可以使用 HTTP GET 调用,而第二个 Create () 方法只能由 HTTP POST 调用。 换句话说,只有在发布 HTML 表单时,才能调用第二个 Create () 方法。 第一个 Create () 方法只返回包含用于创建新联系人的 HTML 窗体的视图。 第二个 Create () 方法更有趣:它将新联系人添加到数据库。

请注意,第二个 Create () 方法已修改为接受 Contact 类的实例。 从 HTML 表单发布的表单值由 ASP.NET MVC 框架自动绑定到此 Contact 类。 HTML 创建窗体中的每个窗体域都分配给 Contact 参数的一个属性。

请注意,Contact 参数使用 [Bind] 属性进行修饰。 [Bind] 属性用于从绑定中排除联系人 ID 属性。 由于 Id 属性表示 Identity 属性,因此我们不希望设置 Id 属性。

在 Create () 方法的正文中,实体框架用于将新的联系人插入数据库。 新的联系人将添加到现有联系人集,并调用 SaveChanges () 方法将这些更改推送回基础数据库。

通过右键单击两个 Create () 方法之一,然后选择菜单选项 “添加视图 ” (请参阅图 16) ,可以生成用于创建新联系人的 HTML 窗体。

显示添加“创建”视图的屏幕截图。

图 16:添加创建视图 (单击以查看全尺寸图像)

“添加视图 ”对话框中,选择 “ContactManager.Models.Contact ”类和用于查看内容的 “创建 ”选项 (请参阅图 17) 。 单击“ 添加” 按钮时,将自动生成“创建”视图。

显示页面爆炸的屏幕截图。

图 17:查看页面爆炸 (单击以查看全尺寸图像)

“创建”视图包含 Contact 类的每个属性的窗体字段。 “创建”视图的代码包含在清单 5 中。

清单 5 - Views\Home\Create.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.Contact>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <%= Html.ValidationSummary() %>

    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="FirstName">FirstName:</label>
                <%= Html.TextBox("FirstName") %>
                <%= Html.ValidationMessage("FirstName", "*") %>
            </p>
            <p>
                <label for="LastName">LastName:</label>
                <%= Html.TextBox("LastName") %>
                <%= Html.ValidationMessage("LastName", "*") %>
            </p>
            <p>
                <label for="Phone">Phone:</label>
                <%= Html.TextBox("Phone") %>
                <%= Html.ValidationMessage("Phone", "*") %>
            </p>
            <p>
                <label for="Email">Email:</label>
                <%= Html.TextBox("Email") %>
                <%= Html.ValidationMessage("Email", "*") %>
            </p>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

修改 Create () 方法并添加“创建”视图后,可以运行 Contact Manger 应用程序并创建新联系人。 单击“索引”视图中显示的“ 新建” 链接,导航到“创建”视图。 应会看到图 18 中的视图。

屏幕截图显示了“创建视图”。

图 18:“创建视图” (单击以查看全尺寸图像)

编辑联系人

添加编辑联系人记录的功能与添加用于创建新联系人记录的功能非常相似。 首先,我们需要将两个新的 Edit 方法添加到 Home 控制器类。 这些新的 Edit () 方法包含在清单 6 中。

列表 6 - Controllers\HomeController.cs (with Edit methods)

//
// GET: /Home/Edit/5

public ActionResult Edit(int id)
{
    var contactToEdit = (from c in _entities.ContactSet
                           where c.Id == id
                           select c).FirstOrDefault();

    return View(contactToEdit);
}

//
// POST: /Home/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
    if (!ModelState.IsValid)
        return View();

    try
    {
        var originalContact = (from c in _entities.ContactSet
                             where c.Id == contactToEdit.Id
                             select c).FirstOrDefault();
        _entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit);
        _entities.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
}

第一个 Edit () 方法由 HTTP GET 操作调用。 Id 参数将传递给此方法,该方法表示正在编辑的联系人记录的 ID。 实体框架用于检索与 ID 匹配的联系人。返回包含用于编辑记录的 HTML 窗体的视图。

第二个 Edit () 方法对数据库执行实际更新。 此方法接受 Contact 类的实例作为参数。 ASP.NET MVC 框架会自动将“编辑”窗体中的表单字段绑定到此类。 请注意,编辑联系人 (需要 id 属性值) 时,不包括 [Bind] 属性。

实体框架用于将修改后的联系人保存到数据库。 必须先从数据库中检索原始联系人。 接下来,调用 Entity Framework ApplyPropertyChanges () 方法来记录对 Contact 的更改。 最后,调用 Entity Framework SaveChanges () 方法将更改保存到基础数据库。

通过右键单击“编辑” () 方法并选择菜单选项“添加视图”,可以生成包含“编辑”窗体的视图。 在“添加视图”对话框中,选择 “ContactManager.Models.Contact ”类和 “编辑 视图内容” (请参阅图 19) 。

显示添加编辑视图的屏幕截图。

图 19:添加编辑视图 (单击以查看全尺寸图像)

单击“添加”按钮时,将自动生成新的“编辑”视图。 生成的 HTML 窗体包含对应于 Contact 类的每个属性的字段 (请参阅列表 7) 。

清单 7 - Views\Home\Edit.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.Contact>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Edit</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit</h2>

    <%= Html.ValidationSummary() %>

    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="FirstName">FirstName:</label>
                <%= Html.TextBox("FirstName") %>
                <%= Html.ValidationMessage("FirstName", "*") %>
            </p>
            <p>
                <label for="LastName">LastName:</label>
                <%= Html.TextBox("LastName") %>
                <%= Html.ValidationMessage("LastName", "*") %>
            </p>
            <p>
                <label for="Phone">Phone:</label>
                <%= Html.TextBox("Phone") %>
                <%= Html.ValidationMessage("Phone", "*") %>
            </p>
            <p>
                <label for="Email">Email:</label>
                <%= Html.TextBox("Email") %>
                <%= Html.ValidationMessage("Email", "*") %>
            </p>
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

删除联系人

如果要删除联系人,则需要将两个 Delete () 操作添加到 Home 控制器类。 第一个删除 () 操作显示删除确认表单。 第二个删除 () 操作执行实际删除。

注意

稍后,在迭代 #7 中,我们将修改联系人管理器,使其支持一步 Ajax 删除。

清单 8 中包含了两个新的 Delete () 方法。

清单 8 - Controllers\HomeController.cs (Delete 方法)

//
// GET: /Home/Delete/5

public ActionResult Delete(int id)
{
    var contactToDelete = (from c in _entities.ContactSet
                         where c.Id == id
                         select c).FirstOrDefault();

    return View(contactToDelete);
}

//
// POST: /Home/Delete/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(Contact contactToDelete)
{
    try
    {
        var originalContact = (from c in _entities.ContactSet
                               where c.Id == contactToDelete.Id
                               select c).FirstOrDefault();

        _entities.DeleteObject(originalContact);
        _entities.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

第一个 Delete () 方法返回用于从数据库中删除联系人记录的确认表单, (请参阅图 20) 。 第二个 Delete () 方法针对数据库执行实际删除操作。 从数据库检索原始联系人后,将调用 Entity Framework DeleteObject () 和 SaveChanges () 方法来执行数据库删除。

屏幕截图显示了删除确认视图。

图 20:删除确认视图 (单击以查看全尺寸图像)

我们需要修改索引视图,使其包含用于删除联系人记录的链接 (请参阅图 21) 。 需要将以下代码添加到包含“编辑”链接的同一表单元格:

Html.ActionLink ( { id=item。Id }) %>

屏幕截图显示了包含“编辑”链接的“索引”视图。

图 21:包含“编辑”链接的索引视图 (单击以查看全尺寸图像)

接下来,我们需要创建删除确认视图。 右键单击主控制器类中的 Delete () 方法,然后选择菜单选项“添加视图”。 “添加视图”对话框 (请参阅图 22) 。

与“列出”、“创建”和“编辑视图”不同,“添加视图”对话框不包含用于创建“删除”视图的选项。 而是选择 ContactManager.Models.Contact 数据类和 视图内容。 选择“空视图内容”选项将要求我们自行创建视图。

显示添加删除确认视图的屏幕截图。

图 22:添加删除确认视图 (单击以查看全尺寸图像)

“删除”视图的内容包含在清单 9 中。 此视图包含一个表单,用于确认是否应删除特定联系人 (请参阅图 21) 。

清单 9 - Views\Home\Delete.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.Contact>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Delete</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Delete</h2>
    
    <p>
    Are you sure that you want to delete the entry for
    <%= Model.FirstName %> <%= Model.LastName %>?
    </p>

    <% using (Html.BeginForm(new { Id = Model.Id }))
       { %>
       <p> 
            <input type="submit" value="Delete" />
        </p>
    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

更改默认控制器的名称

使用联系人的控制器类的名称名为 HomeController 类可能会让你烦恼。 控制器不应命名为 ContactController?

此问题很容易解决。 首先,我们需要重构主控制器的名称。 在Visual Studio Code 编辑器中打开 HomeController 类,右键单击该类的名称,然后选择菜单选项“重构”、“重命名”。 选择此菜单选项将打开“重命名”对话框。

显示重构控制器名称的屏幕截图。

图 23:重构控制器名称 (单击以查看全尺寸图像)

屏幕截图显示了使用“重命名”对话框。

图 24:使用“重命名”对话框 (单击以查看全尺寸图像)

如果重命名控制器类,Visual Studio 还将更新 Views 文件夹中的文件夹名称。 Visual Studio 会将 \Views\Home 文件夹重命名为 \Views\Contact 文件夹。

进行此更改后,应用程序将不再具有主控制器。 运行应用程序时,将看到图 25 中的错误页。

屏幕截图显示无默认控制器。

图 25:无默认控制器 (单击以查看全尺寸图像)

我们需要更新 Global.asax 文件中的默认路由,以使用联系人控制器而不是主控制器。 打开 Global.asax 文件并修改默认路由使用的默认控制器 (请参阅清单 10) 。

清单 10 - Global.asax.cs

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

namespace ContactManager
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Contact", action = "Index", id = "" }  // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

进行这些更改后,联系人管理器将正常运行。 现在,它将使用 Contact 控制器类作为默认控制器。

总结

在第一次迭代中,我们以最快的速度创建了一个基本的 Contact Manager 应用程序。 我们利用 Visual Studio 自动生成控制器和视图的初始代码。 我们还利用 Entity Framework 自动生成数据库模型类。

目前,可以使用 Contact Manager 应用程序列出、创建、编辑和删除联系人记录。 换句话说,我们可以执行数据库驱动的 Web 应用程序所需的所有基本数据库操作。

遗憾的是,我们的应用程序存在一些问题。 首先,我犹豫不决地承认这一点,Contact Manager 应用程序并不是最有吸引力的应用程序。 它需要一些设计工作。 在下一次迭代中,我们将了解如何更改默认视图母版页和级联样式表以改进应用程序的外观。

其次,我们没有实现任何表单验证。 例如,无需为任何窗体字段输入值即可提交“创建联系人”表单。 此外,还可以输入无效的电话号码和电子邮件地址。 我们开始解决迭代 #3 中的表单验证问题。

最后,最重要的是,无法轻松修改或维护 Contact Manager 应用程序的当前迭代。 例如,数据库访问逻辑直接融入控制器操作中。 这意味着,如果不修改控制器,我们就无法修改数据访问代码。 在以后的迭代中,我们将探索可以实现的软件设计模式,使联系人管理器更适应变化。