ASP.NET 网页简介 - 更新数据库数据
本教程介绍如何在使用 ASP.NET 网页 (Razor) 时) 现有数据库条目更新 (更改。 它假定你已完成通过使用 ASP.NET 网页 的窗体输入数据系列。
学习内容:
- 如何在帮助器中选择
WebGrid
单个记录。- 如何从数据库读取单个记录。
- 如何预加载包含数据库记录中的值的窗体。
- 如何更新数据库中的现有记录。
- 如何在不显示页面中存储信息。
- 如何使用隐藏字段来存储信息。
讨论的功能/技术:
- 帮助
WebGrid
程序。- SQL
Update
命令。Database.Execute
方法。- ) (
<input type="hidden">
隐藏字段。
所需操作
在上一教程中,你已了解如何将记录添加到数据库。 在这里,你将了解如何显示要编辑的记录。 在 “电影 ”页中 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.Title
item.Genre
item.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.Execute
和 Validation.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 代码设置的,以便预加载它们。 不过,这一次,你将为该任务使用和 genre
等title
变量,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.ValidationMessage
和 Html.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 网页编程简介教程中,方法(如AsBool
)AsInt
将字符串转换为其他数据类型。 方法 IsInt
(和其他方法(如 IsBool
和 IsDateTime
) )类似。 但是,它们仅 测试是否可以转换 字符串,而不实际执行转换。 因此,在这里,你基本上说 ,如果查询字符串值可以转换为整数...。
另一个潜在的问题是寻找一部不存在的电影。 获取电影的代码如下所示:
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>
其他资源
- 使用 Razor 语法 ASP.NET Web 编程简介
- W3Schools 站点上的 SQL UPDATE 语句