ASP.NET 网页简介 - 更新数据库数据

作者 Tom FitzMacken

本教程介绍如何在使用 ASP.NET 网页 (Razor) 时) 现有数据库条目更新 (更改。 它假定你已完成通过使用 ASP.NET 网页 的窗体输入数据系列。

学习内容:

  • 如何在帮助器中选择 WebGrid 单个记录。
  • 如何从数据库读取单个记录。
  • 如何预加载包含数据库记录中的值的窗体。
  • 如何更新数据库中的现有记录。
  • 如何在不显示页面中存储信息。
  • 如何使用隐藏字段来存储信息。

讨论的功能/技术:

  • 帮助 WebGrid 程序。
  • SQL Update 命令。
  • Database.Execute 方法。
  • ) (<input type="hidden"> 隐藏字段。

所需操作

在上一教程中,你已了解如何将记录添加到数据库。 在这里,你将了解如何显示要编辑的记录。 在 “电影 ”页中 WebGrid ,你将更新帮助程序,使其在每部影片旁边显示 “编辑” 链接:

WebGrid 显示,包括每部电影的“编辑”链接

单击 “编辑” 链接时,会转到其他页面,其中电影信息已在窗体中:

显示要编辑的影片的“编辑影片”页

可以更改任何值。 提交更改时,页面中的代码将更新数据库,并返回到电影列表。

此过程的这一部分的工作方式几乎与在上一教程中创建的 AddMovie.cshtml 页面完全相同,因此本教程中的大部分内容都会很熟悉。

有多种方法可以实现编辑单个电影的方法。 之所以选择显示的方法,是因为它易于实现且易于理解。

首先,你将更新“ 电影 ”页面,以便每个电影列表还包含 “编辑” 链接。

打开 Movies.cshtml 文件。

在页面正文中,通过添加列来更改 WebGrid 标记。 下面是修改后的标记:

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
        grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
        grid.Column("Title"),
        grid.Column("Genre"),
        grid.Column("Year")
    )
)

新列是以下列:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID)">Edit</a>)

此列的要点是显示文本显示“Edit”) <a> 元素 (链接。 我们要做的是创建一个链接,该链接在页面运行时如下所示,每个 id 电影的值都不同:

http://localhost:43097/EditMovie?id=7

此链接将调用名为 EditMovie 的页面,并将查询字符串 ?id=7 传递给该页面。

新列的语法可能看起来有点复杂,但这只是因为它将多个元素组合在一起。 每个元素都很简单。 如果只 <a> 专注于 元素,则会看到以下标记:

<a href="~/EditMovie?id=@item.ID)">Edit</a>

有关网格工作原理的一些背景:网格显示行,每个数据库记录一个行,并显示数据库记录中每个字段的列。 构造每个网格行时, item 对象包含该行 (项) 的数据库记录。 这种排列方式提供了一种在代码中获取该行数据的方法。 这就是你在此处看到的内容:表达式 item.ID 正在获取当前数据库项的 ID 值。 可以使用 、 或 以相同的方式item.Titleitem.Genreitem.Year) 获取标题、流派或年份 (任何数据库值。

表达式 "~/EditMovie?id=@item.ID 将目标 URL (~/EditMovie?id=) 的硬编码部分与此动态派生的 ID 组合在一起。 (在上一教程中看到了 ~ 运算符;它是表示当前网站的 root.ASP.NET 运算符)

结果是列中标记的这一部分在运行时只生成类似于以下标记的内容:

href="/EditMovie?id=2"

当然, 对于每一行, id 的实际值将不同。

为网格列创建自定义显示

现在返回到网格列。 最初在网格中的三列仅显示标题、流派和年份) (数据值。 通过传递数据库列的名称(例如 ) grid.Column("Title")指定了此显示。

此新的 “编辑链接” 列不同。 传递 format 的是参数,而不是指定列名。 通过此参数,可以定义帮助程序将呈现的标记 WebGrid 以及 item 值,以粗体或绿色或所需的任何格式显示列数据。 例如,如果希望标题以粗体显示,则可以创建一个列,如以下示例所示:

grid.Column(format:@<strong>@item.Title</strong>)

(在 属性中看到format的各种@字符标记标记和代码值之间的转换。)

了解 format 属性后,可以更轻松地理解新的 “编辑链接” 列是如何组合在一起的:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),

该列 包含呈现链接的标记,以及一些信息 (从行的数据库记录中提取的 ID) 。

提示

方法的命名参数和位置参数

很多时候,调用方法并向其传递参数时,只需列出用逗号分隔的参数值。 下面是几个示例:

db.Execute(insertCommand, title, genre, year)

Validation.RequireField("title", "You must enter a title")

当你第一次看到此代码时,我们没有提及此问题,但在每种情况下,你都以特定顺序(即在该方法中定义参数的顺序)将参数传递给方法。 对于 db.ExecuteValidation.RequireFields,如果将传递的值的顺序混为一谈,页面运行时会收到错误消息,或者至少会出现一些奇怪的结果。 显然,你必须知道传入参数的顺序。 (在 WebMatrix 中,IntelliSense 可以帮助你了解参数的名称、类型和顺序。)

作为按顺序传递值的替代方法,可以使用 命名参数。 (按顺序传递参数称为使用 位置参数。) 对于命名参数,在传递参数值时显式包含参数的名称。 在这些教程中,已多次使用命名参数。 例如:

var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3)

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
       grid.Column("Title"),
       grid.Column("Genre"),
       grid.Column("Year")
    )
)

命名参数适用于多种情况,尤其是在方法采用多个参数时。 一种是仅希望传递一个或两个参数,但要传递的值不在参数列表中的第一个位置。 另一种情况是,你想要通过按对你最有意义的顺序传递参数,使代码更具可读性。

显然,若要使用命名参数,必须知道参数的名称。 WebMatrix IntelliSense 可以 显示 名称,但它当前无法为你填写这些名称。

创建编辑页

现在可以创建 EditMovie 页面。 当用户单击 “编辑” 链接时,他们将最终访问此页面。

创建名为 EditMovie.cshtml 的页面,并将文件中的内容替换为以下标记:

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
    @Html.ValidationSummary()
    <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
  </body>
</html>

此标记和代码类似于 AddMovie 页中的标记和代码。 提交按钮的文本存在细微差异。 与 AddMovie 页一样,存在一个 Html.ValidationSummary 调用,如果有,则会显示验证错误。 这次我们省去对 的调用 Validation.Message,因为错误将显示在验证摘要中。 如上一教程中所述,可以使用验证摘要和各个错误消息的各种组合。

再次请注意, method 元素的 <form> 属性设置为 post。 与 AddMovie.cshtml 页一样,此页面对数据库进行更改。 因此,此窗体应执行操作 POST 。 (有关 和 POST 操作之间的差异GET的详细信息,请参阅 HTML forms 上的教程中的 GET、POST 和 HTTP 谓词安全边栏。)

如前面的教程所示, value 文本框的属性是使用 Razor 代码设置的,以便预加载它们。 不过,这一次,你将为该任务使用和 genretitle变量,Request.Form["title"]而不是 :

<input type="text" name="title" value="@title" />

与之前一样,此标记将预加载带有电影值的文本框值。 稍后你将看到为什么这次使用变量而不是 使用 Request 对象会很方便。

此页上还有一个 <input type="hidden"> 元素。 此元素存储电影 ID 而不使其在页面上可见。 ID 最初使用 URL) 中的查询字符串值 (?id=7 或类似值传递到页面。 通过将 ID 值放入隐藏字段,可以确保在提交表单时它可用,即使你不再有权访问调用页面时使用的原始 URL。

AddMovie 页不同, EditMovie 页的代码具有两个不同的函数。 第一个函数是,当页面首次显示 (,然后 ) 时,代码将从查询字符串获取电影 ID。 然后,代码使用该 ID 从数据库中读取相应的电影,并在文本框中显示) 预加载 (。

第二个函数是当用户单击“ 提交更改” 按钮时,代码必须读取文本框的值并对其进行验证。 代码还必须使用新值更新数据库项。 此方法类似于添加记录,如 AddMovie 中所示。

添加代码以阅读单个电影

若要执行第一个函数,请将以下代码添加到页面顶部:

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty()){
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }
}

此代码的大部分位于启动 if(!IsPost)的块内。 运算符 ! 表示“not”,因此表达式表示 此请求是否不是发布提交,这是一种间接方式,表示 此请求是否是第一次运行此页面。 如前所述,此代码应 仅在 页面首次运行时运行。 如果未将代码括在 中 if(!IsPost),它将在每次调用页面时运行,无论是第一次还是响应按钮单击。

请注意,代码这次包含一个 else 块。 正如我们在引入块时所说 if ,如果测试的条件不正确,有时你希望运行替代代码。 这里就是这样。 如果条件通过 (即,如果传递到页面的 ID) 正常,则从数据库读取一行。 但是,如果条件未通过,则块将 else 运行,代码将设置错误消息。

验证传递到页面的值

代码使用 Request.QueryString["id"] 获取传递到页面的 ID。 代码确保实际为 ID 传递了值。 如果未传递任何值,则代码将设置验证错误。

此代码显示了验证信息的不同方法。 在上一教程中,你已使用 Validation 帮助程序。 你注册了要验证的字段,ASP.NET 使用 Html.ValidationMessageHtml.ValidationSummary自动执行验证并显示错误。 但是,在这种情况下,你并没有真正验证用户输入。 相反,你正在验证从其他位置传递到页面的值。 帮助 Validation 程序不会为你执行此操作。

因此,可以通过使用 if(!Request.QueryString["ID"].IsEmpty()) 测试值,自行检查该值。 如果出现问题,可以使用 来显示错误 Html.ValidationSummary,就像对 Validation 帮助程序所做的那样。 为此,请调用 Validation.AddFormError 并向其传递要显示的消息。 Validation.AddFormError 是一种内置方法,可用于定义与你熟悉的验证系统绑定的自定义消息。 (本教程的后面部分,我们将讨论如何使此验证过程更加可靠。)

确保电影有 ID 后,代码读取数据库,只查找单个数据库项。 (你可能注意到了数据库操作的常规模式:打开数据库、定义 SQL 语句并运行语句。) 这次 SQL Select 语句包括 WHERE ID = @0。 由于 ID 是唯一的,因此只能返回一条记录。

查询通过使用 db.QuerySingle (而不是 db.Query执行,因为用于电影列表) ,并且代码会将结果放入 row 变量中。 名称是任意的 row ;你可以为任何喜欢的变量命名。 然后,在顶部初始化的变量将填充电影详细信息,以便可以在文本框中显示这些值。

测试编辑页 (到目前为止)

如果要测试页面,请立即运行 “电影 ”页面,然后单击任何电影旁边的 “编辑” 链接。 你将看到 EditMovie 页面,其中填写了所选电影的详细信息:

屏幕截图显示“编辑影片”页面,其中显示了要编辑的影片。

请注意,页面的 URL 包含类似 ?id=10 (或其他数字) 。 到目前为止,你已经测试了“电影”页面中的“编辑链接”是否正常工作,你的页面是否从查询字符串读取 ID,以及用于获取单个电影记录的数据库查询是否正常工作。

可以更改电影信息,但单击“ 提交更改”时不会发生任何操作。

添加代码以使用用户的更改更新影片

EditMovie.cshtml 文件中,若要实现第二个函数 (保存更改) ,请在块的 @ 右大括号内添加以下代码。 (如果不确定代码的确切放置位置,可以查看本教程末尾显示的 “编辑电影”页面的完整代码列表 。)

if(IsPost){
    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");
    Validation.RequireField("movieid", "No movie ID was submitted!");

    title = Request.Form["title"];
    genre = Request.Form["genre"];
    year = Request.Form["year"];
    movieId = Request.Form["movieId"];

    if(Validation.IsValid()){
        var db = Database.Open("WebPagesMovies");
        var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
        db.Execute(updateCommand, title, genre, year, movieId);
        Response.Redirect("~/Movies");
   }
}

同样,此标记和代码类似于 AddMovie 中的代码。 代码位于块 if(IsPost) 中,因为此代码仅在用户单击“ 提交更改” 按钮(即 (时)运行,并且仅在) 表单已发布时运行。 在本例中,你使用的不是这样的 if(IsPost && Validation.IsValid())测试,也就是说,你不会使用 AND 来组合这两个测试。 在此页中,首先确定是否有表单提交 () if(IsPost) ,然后才注册字段以供验证。 然后,可以 () if(Validation.IsValid() 测试验证结果。 流与 AddMovie.cshtml 页略有不同,但效果相同。

通过使用 和其他<input>元素的类似代码获取文本框Request.Form["title"]的值。 请注意,这一次,代码将从隐藏字段 (<input type="hidden">) 获取电影 ID。 当页面首次运行时,代码会从查询字符串中获取 ID。 从隐藏字段中获取值,以确保获取最初显示的电影的 ID,以防查询字符串自那时以来发生某种更改。

AddMovie 代码与此代码之间的真正重要区别在于,在此代码中使用 SQL Update 语句而不是 Insert Into 语句。 以下示例演示 SQL Update 语句的语法:

UPDATE table SET col1="value", col2="value", col3="value" ... WHERE ID = value

可以按任意顺序指定任何列,并且不必在操作期间 Update 更新每个列。 (无法更新 ID 本身,因为这实际上会将记录保存为新记录,并且操作不允许 Update 此操作。)

注意

重要Where具有 ID 的 子句非常重要,因为数据库就是这样知道要更新哪个数据库记录的。 如果关闭 Where 子句,数据库将更新数据库中 的每 条记录。 在大多数情况下,这将是一场灾难。

在代码中,使用占位符将更新的值传递到 SQL 语句。 若要重复前面所述:出于安全原因, 请仅 使用占位符将值传递给 SQL 语句。

代码使用 db.Execute 运行 Update 语句后,它会重定向回列表页,你可以在其中查看更改。

提示

不同的 SQL 语句、不同的方法

你可能已经注意到,使用略有不同的方法来运行不同的 SQL 语句。 若要运行 Select 可能返回多个记录的查询,请使用 Query 方法。 若要运行 Select 已知仅返回一个数据库项的查询,请使用 QuerySingle 方法。 若要运行做出更改但不返回数据库项的命令,请使用 Execute 方法。

必须使用不同的方法,因为每个方法都返回不同的结果,正如你在 和 QuerySingle之间的差异Query中看到的那样。 (方法 Execute 实际上还返回一个值(即受 命令影响的数据库行数),但到目前为止,你一直忽略该值。)

当然, Query 方法可能只返回一个数据库行。 但是,ASP.NET 始终将 方法的结果 Query 视为集合。 即使方法只返回一行,你也不得不从集合中提取该单行。 因此,在 知道 只返回一行的情况下,使用 QuerySingle会更方便一些。

还有一些其他方法可执行特定类型的数据库操作。 可以在 ASP.NET 网页 API 快速参考中找到数据库方法的列表。

使 ID 验证更加可靠

第一次运行页面时,将从查询字符串获取电影 ID,以便可以从数据库获取该电影。 你确保实际上有一个值要去查找,这是你使用此代码完成的:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty()){
        // Etc.
    }
}

你使用此代码来确保如果用户在没有先选择“电影”页中的电影的情况下访问 EditMovies 页面,该页面将显示用户友好的错误消息。 (否则,用户会看到一个错误,可能只会混淆他们。)

但是,此验证不是很可靠。 可能还会调用页面并出现以下错误:

  • ID 不是数字。 例如,可以使用 URL(如 http://localhost:nnnnn/EditMovie?id=abc)调用页面。
  • ID 是一个数字,但它引用 (不存在的电影, http://localhost:nnnnn/EditMovie?id=100934 例如,) 。

如果有兴趣查看这些 URL 导致的错误,请运行 “电影 ”页。 选择要编辑的电影,然后将 EditMovie 页面的 URL 更改为包含字母 ID 或不存在的电影 ID 的 URL。

那么,你应该怎么做呢? 第一个解决方法是确保不仅 ID 传递给页面,而且该 ID 是整数。 更改测试的代码 !IsPost ,如下所示:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
       // Etc.

你已向 IsEmpty 测试添加了第二个条件,并将其链接到 && (逻辑 AND) :

Request.QueryString["ID"].IsInt()

你可能还记得在 ASP.NET 网页编程简介教程中,方法(如AsBoolAsInt将字符串转换为其他数据类型。 方法 IsInt (和其他方法(如 IsBoolIsDateTime) )类似。 但是,它们仅 测试是否可以转换 字符串,而不实际执行转换。 因此,在这里,你基本上说 ,如果查询字符串值可以转换为整数...

另一个潜在的问题是寻找一部不存在的电影。 获取电影的代码如下所示:

var row = db.QuerySingle(dbCommand, movieId);

如果将值 movieId 传递给 QuerySingle 与实际电影不对应的方法,则不会返回任何内容,例如 title=row.Title , (后面的语句) 导致错误。

同样,还有一个简单的解决方法。 db.QuerySingle如果方法不返回任何结果,则该row变量将为 null。 因此,在尝试从变量获取值之前,row可以检查变量是否为 null。 以下代码在 语句周围添加一个 if 块,用于从 对象中 row 获取值:

if(row != null) {
    title = row.Title;
    genre = row.Genre;
    year = row.Year;
}
else{
    Validation.AddFormError("No movie was found for that ID.");
}

通过这两个附加的验证测试,页面变得更加防弹。 分支的完整代码 !IsPost 现在如下所示:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
        movieId = Request.QueryString["ID"];
        var db = Database.Open("WebPagesMovies");
        var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
        var row = db.QuerySingle(dbCommand, movieId);

        if(row != null) {
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else {
            Validation.AddFormError("No movie was found for that ID.");
        }
    }
    else {
        Validation.AddFormError("No movie was selected.");
    }
}

我们将再次指出,此任务非常适合 else 用于块。 如果测试未通过,则 else 块将设置错误消息。

最后一个有用的详细信息是将链接添加回 “电影 ”页面。 在普通事件流中,用户将从 “电影 ”页开始并单击 “编辑” 链接。 这会将他们带到 EditMovie 页面,他们可以在其中编辑电影并单击按钮。 代码处理更改后,会重定向回 “电影 ”页。

但是:

  • 用户可能决定不更改任何内容。
  • 用户可能已访问此页面,而无需先单击“电影”页中的“编辑”链接。

无论采用哪种方式,你都希望让他们轻松返回到main列表。 这是一个简单的解决方法 - 在标记的结束 </form> 标记后面添加以下标记:

<p><a href="~/Movies">Return to movie listing</a></p>

此标记使用 <a> 与在其他位置看到的元素相同的语法。 URL 包括 ~ 表示“网站的根”。

测试电影更新过程

现在可以测试了。 运行 “电影 ”页,然后单击电影旁边的“ 编辑 ”。 出现 “编辑影片” 页面时,对影片进行更改,然后单击“ 提交更改”。 当电影列表出现时,请确保显示所做的更改。

若要确保验证正常工作,请单击“ 编辑 ”另一部电影。 访问 EditMovie 页面时,清除 “流派 ”字段 (或 Year 字段,或同时) 并尝试提交更改。 你将看到一个错误,如预期的那样:

显示验证错误的“编辑影片”页

单击“ 返回到电影列表 ”链接,放弃更改并返回到 “电影 ”页面。

即将推出下一步

在下一教程中,你将了解如何删除电影记录。

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

    if(!Request.QueryString["searchTitle"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
        searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Movies</title>
        <style type="text/css">
          .grid { margin: 4px; border-collapse: collapse; width: 600px; }
          .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
          .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
          .alt { background-color: #E8E8E8; color: #000; }
        </style>
    </head>
    <body>
        <h1>Movies</h1>
          <form method="get">
              <div>
                <label for="searchGenre">Genre to look for:</label>
                <input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
                <input type="Submit" value="Search Genre" /><br/>
                (Leave blank to list all movies.)<br/>
                </div>

              <div>
                  <label for="SearchTitle">Movie title contains the following:</label>
                  <input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
                  <input type="Submit" value="Search Title" /><br/>
                </div>
            </form>

        <div>
             @grid.GetHtml(
                tableStyle: "grid",
                headerStyle: "head",
                alternatingRowStyle: "alt",
                columns: grid.Columns(
                    grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
                    grid.Column("Title"),
                    grid.Column("Genre"),
                    grid.Column("Year")
                )
            )
        </div>
    <p>
        <a href="~/AddMovie">Add a movie</a>
    </p>
    </body>
</html>

“编辑电影”页面的完整页面列表

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);

            if(row != null) {
                title = row.Title;
                genre = row.Genre;
                year = row.Year;
            }
            else{
                Validation.AddFormError("No movie was selected.");
            }
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }

    if(IsPost){
        Validation.RequireField("title", "You must enter a title");
        Validation.RequireField("genre", "Genre is required");
        Validation.RequireField("year", "You haven't entered a year");
        Validation.RequireField("movieid", "No movie ID was submitted!");

        title = Request.Form["title"];
        genre = Request.Form["genre"];
        year = Request.Form["year"];
        movieId = Request.Form["movieId"];

        if(Validation.IsValid()){
            var db = Database.Open("WebPagesMovies");
            var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
            db.Execute(updateCommand, title, genre, year, movieId);
            Response.Redirect("~/Movies");
        }
    }
}

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
      @Html.ValidationSummary()
      <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
    <p><a href="~/Movies">Return to movie listing</a></p>
  </body>
</html>

其他资源