改进 Details 和 Delete 方法 (C#)

作者: 里克·安德森

注意

此处提供了本教程的更新版本,它使用 ASP.NET MVC 5 和 Visual Studio 2013。 它更安全,更易于遵循并演示更多功能。

本教程将介绍如何使用 Microsoft Visual Web Developer 2010 Express Service Pack 1 生成 ASP.NET MVC Web 应用程序的基本知识,这是 visual Studio 的免费 Microsoft版本。 在开始之前,请确保已安装下面列出的先决条件。 可以通过单击以下链接来安装所有这些组件: Web 平台安装程序。 或者,可使用以下链接单独安装各个必备软件:

如果使用 Visual Studio 2010 而不是 Visual Web Developer 2010,请单击以下链接安装必备组件: Visual Studio 2010 先决条件

带有 C# 源代码的 Visual Web 开发人员项目随本主题一起提供。 下载 C# 版本。 如果更喜欢 Visual Basic,请切换到 本教程的 Visual Basic 版本

在本教程的这一部分中,你将对自动生成 Details 的方法和 Delete 方法进行一些改进。 这些更改不是必需的,但只需少量代码,即可轻松增强应用程序。

改进详细信息和删除方法

在搭建控制器基架 Movie 时,ASP.NET MVC 生成的代码非常出色,但只需进行少量更改即可更可靠。

Movie打开控制器并通过在找不到电影时返回HttpNotFound来修改Details方法。 还应修改 Details 方法以设置传递给它的 ID 的默认值。 (在本教程的第 6 部分中对方法进行了类似的更改Edit。但是,必须更改方法的Details返回类型,ActionResult因为HttpNotFound该方法不返回对象ViewResultViewResult 以下示例显示了修改 Details 的方法。

public ActionResult Details(int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

使用 Code First 可以轻松使用 Find 该方法搜索数据。 我们内置在方法中的一个重要安全功能是,代码 Find 在代码尝试执行任何操作之前验证方法是否已找到电影。 例如,一个黑客可能通过将链接创建的 URL 从 http://localhost:xxxx/Movies/Details/1 更改为类似 http://localhost:xxxx/Movies/Details/12345 的值(或者不代表任何实际电影的其他值)将错误引入站点。 如果未检查 null 电影,则可能会导致数据库错误。

同样,更改 DeleteDeleteConfirmed 方法以指定 ID 参数的默认值,并在找不到电影时返回 HttpNotFound 。 控制器中的Movie更新Delete方法如下所示。

// GET: /Movies/Delete/5

public ActionResult Delete(int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

//
// POST: /Movies/Delete/5

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    db.Movies.Remove(movie);
    db.SaveChanges();
    return RedirectToAction("Index");
}

请注意,该方法 Delete 不会删除数据。 执行删除操作以响应 GET 请求(或者说,执行编辑操作、创建操作或更改数据的任何其他操作)会打开安全漏洞。

删除数据的 HttpPost 方法命名为 DeleteConfirmed,以便为 HTTP POST 方法提供一个唯一的签名或名称。 下面显示了两个方法签名:

// GET: /Movies/Delete/5
public ActionResult Delete(int id = 0)

//
// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id = 0)

公共语言运行时(CLR)要求重载的方法具有唯一的签名(同名、不同的参数列表)。 但是,此处需要两个 Delete 方法 -- 一个用于 GET,一个用于 POST - 这两种方法都需要相同的签名。 (它们都需要接受单个整数作为参数。)

若要解决此问题,可以执行一些操作。 一个是为方法提供不同的名称。 这就是我们在前面的示例中所做的。 但是,这会造成一个小问题:ASP.NET 按名称将 URL 段映射到操作方法,如果重命名方法,则路由通常无法找到该方法。 该示例中也提供了解决方案,即向 DeleteConfirmed 方法添加 ActionName("Delete") 属性。 这有效地执行路由系统的映射,以便包含 /Delete/for a POST 请求的 URL 将找到 DeleteConfirmed 该方法。

避免具有相同名称和签名的方法出现问题的另一种方法是人为地更改 POST 方法的签名以包含未使用的参数。 例如,某些开发人员添加传递给 POST 方法的参数类型 FormCollection ,然后根本不使用参数:

public ActionResult Delete(FormCollection fcNotUsed, int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    db.Movies.Remove(movie);
    db.SaveChanges();
    return RedirectToAction("Index");
}

总结

现在,你已拥有一个完整的 ASP.NET MVC 应用程序,用于在 SQL Server Compact 数据库中存储数据。 可以创建、读取、更新、删除和搜索电影。

显示 M V C 电影应用中的“搜索索引”页的屏幕截图。该页显示四部电影的列表。

本基本教程让你开始制作控制器,将它们与视图相关联,并围绕硬编码的数据传递。 然后,你创建了一个数据模型并设计了一个数据模型。 实体框架代码首先从数据模型动态创建了一个数据库,ASP.NET MVC 基架系统自动生成了基本 CRUD 操作的操作方法和视图。 然后,你添加了一个搜索表单,允许用户搜索数据库。 你更改了数据库以包含一个新数据列,然后更新了两个页面以创建并显示此新数据。 通过用命名空间中的 DataAnnotations 属性标记数据模型来添加验证。 生成的验证在客户端和服务器上运行。

如果想要部署应用程序,最好先在本地 IIS 7 服务器上测试应用程序。 可以使用此 Web 平台安装程序 链接为 ASP.NET 应用程序启用 IIS 设置。 请参阅以下部署链接:

现在,我鼓励你继续学习 适用于 ASP.NET MVC 应用程序和 MVC 音乐存储 的实体框架数据模型,探索 MSDN 上的 ASP.NET 文章,并查看许多视频和资源 https://asp.net/mvc ,了解有关 ASP.NET MVC 的详细信息! ASP.NET MVC 论坛是提出问题的绝佳场所。

请尽情体验吧!

— 斯科特·汉塞尔曼(http://hanselman.com推特上的@shanselman )和里克·安德森 blogs.msdn.com/rickAndy