ASP.NET Web Pages簡介 - 使用表單輸入資料庫資料
本教學課程說明如何建立專案表單,然後在您使用 ASP.NET Web Pages (Razor) 時,將表單中的資料輸入資料庫資料表。 它假設您已透過ASP.NET Web Pages 中的 HTML 表單基本概念來完成系列。
您將學到什麼:
- 深入瞭解如何處理輸入表單。
- 如何在資料庫中新增 (插入) 資料。
- 如何確定使用者已以表單輸入必要的值, (如何驗證使用者輸入) 。
- 如何顯示驗證錯誤。
- 如何從目前頁面跳至另一個頁面。
討論的功能/技術:
Database.Execute
方法- SQL
Insert Into
語句- 協助
Validation
程式。Response.Redirect
方法
您要建置的內容
在稍早示範如何建立資料庫的教學課程中,您會直接在 WebMatrix 中編輯資料庫,在 [資料庫 ] 工作區中編輯資料庫來輸入資料庫資料。 不過,在大部分應用程式中,這不是將資料放入資料庫中的實際方式。 因此在本教學課程中,您將建立 Web 型介面,讓您或任何人輸入資料並將其儲存至資料庫。
您將建立一個頁面,您可以在其中輸入新的電影。 頁面將包含欄位 (文字方塊的專案表單,) 您可以在其中輸入電影標題、內容類型和年份。 頁面看起來會像這個頁面:
文字方塊將會是類似此標記的 HTML <input>
元素:
<input type="text" name="genre" value="" />
建立基本專案表單
建立名為 AddMovie.cshtml的頁面。
以下列標記取代 檔案中的內容。 覆寫所有專案;您很快就會在頂端新增程式碼區塊。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
</head>
<body>
<h1>Add a Movie</h1>
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@Request.Form["title"]" />
</p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
</p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
</p>
<p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
</fieldset>
</form>
</body>
</html>
此範例顯示建立表單的一般 HTML。 它會針對文字方塊和送出按鈕使用 <input>
元素。 文字方塊的標題是使用標準 <label>
元素所建立。 <fieldset>
和 <legend>
元素會將良好的方塊放在表單周圍。
請注意,在此頁面中 <form>
,元素會使用 post
做為 屬性的值 method
。 在上一個教學課程中,您已建立使用 方法的 get
表單。 正確,因為雖然表單已提交值至伺服器,但要求並未進行任何變更。 它所做的一切都是以不同的方式擷取資料。 不過,在此頁面中, 您將 進行變更-您要新增資料庫記錄。 因此,這個表單應該使用 post
方法。 (如需 和 POST
作業之間的差異 GET
的詳細資訊,請參閱上一個教學課程中的GET、POST 和 HTTP 動詞安全提要欄。)
請注意,每個文字方塊都有元素 name
(title
、 genre
year
) 。 如您在上一個教學課程中所見,這些名稱很重要,因為您必須擁有這些名稱,以便稍後取得使用者的輸入。 您可以使用任何名稱。 使用有意義的名稱有助於記住您正在使用的資料。
value
每個 <input>
元素的 屬性都包含一些 Razor 程式碼 (, Request.Form["title"]
例如,) 。 您已在上一個教學課程中學到此訣竅的版本,以在提交表單之後保留輸入至文字方塊的值, () 。
取得表單值
接下來,您會新增處理表單的程式碼。 在大綱中,您將執行下列動作:
- 檢查是否已在提交 (張貼頁面) 。 只有當使用者按一下按鈕,而不是第一次執行頁面時,才想要讓程式碼執行。
- 取得使用者輸入文字方塊的值。 在此情況下,因為表單正在使用
POST
動詞,所以您會從Request.Form
集合中取得表單值。 - 在 Movies 資料庫資料表中,將值插入為新記錄。
在檔案頂端,新增下列程式碼:
@{
var title = "";
var genre = "";
var year = "";
if(IsPost){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
}
}
前幾行會建立變數 (title
、 genre
和 year
) ,以保存文字方塊中的值。 這一行 if(IsPost)
可確保只有在使用者按一下 [新增電影]按鈕時才會設定變數,也就是在表單張貼時。
如先前教學課程中所見,您會使用類似 Request.Form["name"]
的運算式取得文字方塊的值,其中 name 是元素的名稱 <input>
。
(、 genre
和 year
) 變數的名稱 title
是任意的。 就像您指派給 <input>
元素的名稱一樣,您可以呼叫任何您想要的名稱。 (變數的名稱不需要符合 form.) 上的專案名稱屬性 <input>
,但與 <input>
專案相同,最好使用反映其包含資料的變數名稱。 當您撰寫程式碼時,一致的名稱可讓您更輕鬆地記住您正在使用的資料。
將資料新增至資料庫
在您剛才新增的程式碼區塊中,只 位於 區塊的右大括弧 ( }
if
) (,而不只是程式碼區塊內部) ,請新增下列程式碼:
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) VALUES(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
此範例類似于您在上一個教學課程中用來擷取和顯示資料的程式碼。 開頭 db =
為 的行會開啟資料庫,例如之前,下一行會再次定義 SQL 語句,如您先前所見。 不過,這次會定義 SQL Insert Into
語句。 下列範例顯示 語句的 Insert Into
一般語法:
INSERT INTO table (column1, column2, column3, ...) VALUES (value1, value2, value3, ...)
換句話說,您可以指定要插入的資料表,然後列出要插入的資料行,然後列出要插入的值。 (如前所述,SQL 不區分大小寫,但有些人會將關鍵字大寫,讓讀取 command.)
您要插入的資料行已經列在命令中 - (Title, Genre, Year)
。 有趣的部分是從文字方塊取得值到 VALUES
命令的一部分。 除了實際值外,您會看到 @0
、 @1
、 和 @2
,當然是預留位置。 當您在行) 上 db.Execute
執行命令 (時,您會傳遞您從文字方塊取得的值。
重要! 請記住,您應該在 SQL 語句中包含使用者線上輸入資料的唯一方式是使用預留位置,如這裡所示 (VALUES(@0, @1, @2)
) 。 如果您將使用者輸入串連至 SQL 語句,您可以自行進入 SQL 插入式攻擊,如上一個教學課程) ASP.NET Web Pages (中的表單基本概念中所述。
仍在 區塊內 if
,在 行後面 db.Execute
新增下列這一行:
Response.Redirect("~/Movies");
在新電影插入資料庫之後,這一行會將您 (重新導向至影片頁面) ,讓您可以看到您剛輸入的 電影 。 運算子 ~
表示「網站的根目錄」, (運算子 ~
只能在 ASP.NET 網頁中運作,而不是在 HTML 中一般運作。)
完整的程式碼區塊看起來像下列範例:
@{
var title = "";
var genre = "";
var year = "";
if(IsPost){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
測試到目前為止 (插入命令)
您尚未完成,但現在是測試的好時機。
在 WebMatrix 中檔案的樹狀檢視中,以滑鼠右鍵按一下 [AddMovie.cshtml ] 頁面,然後按一下 [在瀏覽器中啟動]。
(如果您最後在瀏覽器中使用不同的頁面,請確定 URL 是 http://localhost:nnnnn/AddMovie
) ,其中 nnnnn 是您使用的埠號碼。)
您是否收到錯誤頁面? 如果是,請仔細閱讀,並確定程式碼看起來確實是稍早列出的內容。
在表單中輸入電影,例如,使用「公民假名」、「老式」和「1941」。 (或任何.) 然後按一下 [ 新增電影]。
如果一切順利,系統會將您重新導向至 [電影] 頁面。 請確定您的新電影已列出。
驗證使用者輸入
返回至AddMovie頁面,或再次執行。 輸入另一部電影,但這次只輸入標題,例如,在雨中輸入 「Singin'」。 然後按一下 [新增電影]。
系統會再次重新導向至 [電影] 頁面。 您可以找到新的電影,但不完整。
當您建立 Movies 資料表時,您明確表示沒有任何欄位可以是 Null。 在這裡,您有新電影的專案表單,而且您會將欄位保留空白。 這是錯誤。
在此情況下,資料庫實際上不會引發 (或 擲 回) 錯誤。 您未提供內容類型或年份,因此 AddMovie 頁面中的程式碼會將這些值視為所謂的 空字串。 當 SQL Insert Into
命令執行時,內容類型和年份欄位在它們中沒有有用的資料,但它們不是 Null。
很明顯地,您不想讓使用者在資料庫中輸入半空的電影資訊。 解決方案是驗證使用者的輸入。 一開始,驗證只會確保使用者已針對所有欄位輸入值 (,也就是沒有任何欄位包含空字串) 。
提示
Null 和空字串
在程式設計中,不同概念「無值」有區別。一般而言,如果值從未以任何方式設定或初始化,則值為 null 。 相反地,預期字元資料 (字串) 變數可以設定為 空字串。 在此情況下,此值不是 null;它只是明確設定為長度為零的字元字串。 這兩個語句顯示差異:
var firstName; // Not set, so its value is null
var firstName = ""; // Explicitly set to an empty string -- not null
這比這樣複雜一點,但重點在於代表 null
一種未決定的狀態。
現在和之後,請務必確切瞭解值是否為 Null,以及何時只是空字串。 在 AddMovie 頁面的程式碼中,您會使用 Request.Form["title"]
等來取得文字方塊的值。 當您按一下按鈕) 之前,頁面第一次執行 (時,的值 Request.Form["title"]
會是 null。 但是當您提交表單時, Request.Form["title"]
會取得文字方塊的值 title
。 這並不明顯,但空白文字方塊不是 Null;它只會有空字串。 因此,當程式碼執行以回應按鈕按一下時, Request.Form["title"]
其中會有空字串。
為什麼這項區別很重要? 當您建立 Movies 資料表時,您明確表示沒有任何欄位可以是 Null。 但在這裡,您有新電影的專案表單,而且您會將欄位保留空白。 當您嘗試儲存沒有內容類型或年份值的新電影時,您會合理地預期資料庫會抱怨。 但這是一點,即使您將這些文字方塊保留空白,這些值也不會是 Null;它們是空字串。 因此,您可以將新的電影儲存到資料庫,這些資料行空白,但不是 Null! — 值。 因此,您必須確定使用者不會提交空字串,您可以藉由驗證使用者的輸入來執行此動作。
驗證協助程式
ASP.NET Web Pages包含協助程式 — Validation
協助程式 , 您可用來確保使用者輸入符合您需求的資料。 協助 Validation
程式是內建 ASP.NET Web Pages的其中一個協助程式,因此您不需要使用 NuGet 將它安裝為套件,這是您在先前教學課程中安裝 Gravatar 協助程式的方式。
若要驗證使用者的輸入,您將執行下列動作:
- 使用程式碼來指定您想要在頁面上的文字方塊中要求值。
- 將測試放入程式碼中,只有當所有專案都正確驗證時,才會將電影資訊新增至資料庫。
- 將程式碼新增至標記,以顯示錯誤訊息。
在 AddMovie 頁面的程式碼區塊中,緊接在變數宣告之前的頂端,新增下列程式碼:
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
一次 (<input>
元素,) 您想要輸入的專案。 您也可以為每個呼叫新增自訂錯誤訊息,如這裡所示。 (我們只會改變訊息,以顯示您可以在那裡放置任何專案。)
如果發生問題,您想要防止新的電影資訊插入資料庫中。 在 區塊中 if(IsPost)
,使用 &&
(邏輯 AND) 來新增另一個測試 Validation.IsValid()
的條件。 當您完成時,整個 if(IsPost)
區塊看起來會像下列程式碼:
if(IsPost && Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
如果使用協助程式註冊 Validation
的任何欄位發生驗證錯誤,則方法會 Validation.IsValid
傳回 false。 在此情況下,該區塊中的任何程式碼都不會執行,因此不會將不正確電影專案插入資料庫中。 當然,您不會重新導向至 [電影] 頁面。
完整的程式碼區塊,包括驗證程式代碼,現在看起來像下列範例:
@{
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
var title = "";
var genre = "";
var year = "";
if(IsPost && Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
顯示驗證錯誤
最後一個步驟是顯示任何錯誤訊息。 您可以顯示每個驗證錯誤的個別訊息,也可以顯示摘要或兩者。 在本教學課程中,您將執行這兩項作業,以查看其運作方式。
在您正在驗證的每個 <input>
專案旁邊,呼叫 Html.ValidationMessage
方法,並將您正在驗證的專案 <input>
名稱傳遞給它。 您會將方法放在 Html.ValidationMessage
您想要顯示錯誤訊息的位置。 當頁面執行時, Html.ValidationMessage
方法會轉譯 <span>
驗證錯誤將會傳回的專案。 (如果沒有錯誤,則會 <span>
轉譯元素,但其中沒有文字。)
變更頁面中的標記,使其包含頁面上三 <input>
個 Html.ValidationMessage
元素的方法,如下列範例所示:
<p><label for="title">Title:</label>
<input type="text" name="title" value="@Request.Form["title"]" />
@Html.ValidationMessage("title")
</p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
@Html.ValidationMessage("genre")
</p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
@Html.ValidationMessage("year")
</p>
若要查看摘要的運作方式,也請在頁面上的 元素後面 <h1>Add a Movie</h1>
新增下列標記和程式碼:
@Html.ValidationSummary()
根據預設, Html.ValidationSummary
方法會顯示清單中的所有驗證訊息, (<ul>
元素內 <div>
的專案) 。 如同 Html.ValidationMessage
方法,驗證摘要的標記一律會轉譯;如果沒有錯誤,則不會轉譯任何清單專案。
摘要可以是顯示驗證訊息的替代方式,而不是使用 Html.ValidationMessage
方法來顯示每個欄位特定的錯誤。 或者,您可以使用摘要和詳細資料。 或者, Html.ValidationSummary
您可以使用 方法來顯示一般錯誤,然後使用個別 Html.ValidationMessage
呼叫來顯示詳細資料。
完整頁面現在看起來像下列範例:
@{
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
var title = "";
var genre = "";
var year = "";
if(IsPost && Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
</head>
<body>
<h1>Add 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="@Request.Form["title"]" />
@Html.ValidationMessage("title")
</p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
@Html.ValidationMessage("genre")
</p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
@Html.ValidationMessage("year")
</p>
<p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
</fieldset>
</form>
</body>
</html>
這樣就大功告成了。 您現在可以藉由新增電影來測試頁面,但排除一或多個欄位。 當您這樣做時,您會看到下列錯誤顯示:
設定驗證錯誤訊息的樣式
您可以看到有錯誤訊息,但它們並不非常醒眼。 不過,有一個簡單的方式來設定錯誤訊息的樣式。
若要設定 所 Html.ValidationMessage
顯示之個別錯誤訊息的樣式,請建立名為 的 field-validation-error
CSS 樣式類別。 若要定義驗證摘要的尋找,請建立名為 的 validation-summary-errors
CSS 樣式類別。
若要查看這項技術的運作方式,請在頁面的 區段內 <head>
新增 <style>
元素。 然後定義名為 field-validation-error
且 validation-summary-errors
包含下列規則的樣式類別:
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
<style type="text/css">
.field-validation-error {
font-weight:bold;
color:red;
background-color:yellow;
}
.validation-summary-errors{
border:2px dashed red;
color:red;
background-color:yellow;
font-weight:bold;
margin:12px;
}
</style>
</head>
一般而言,您可能會將樣式資訊放入個別 的 .css 檔案中,但為了簡單起見,您現在可以將它們放在頁面中。 (本教學課程集稍後,您會將 CSS 規則移至個別 的 .css 檔案.)
如果發生驗證錯誤,方法會 Html.ValidationMessage
轉譯 <span>
包含 的專案 class="field-validation-error"
。 藉由新增該類別的樣式定義,您可以設定訊息的外觀。 如果發生錯誤,方法 ValidationSummary
同樣會動態轉譯 屬性 class="validation-summary-errors"
。
再次執行頁面,並刻意省略幾個欄位。 錯誤現在更明顯。 (事實上,它們已過度使用,但只是為了顯示您可以執行的動作。)
新增影片頁面的連結
最後一個步驟是方便從原始電影清單前往 AddMovie 頁面。
再次開啟 [電影] 頁面。 在協助程式後面的 WebGrid
結尾 </div>
標記之後,新增下列標記:
<p>
<a href="~/AddMovie">Add a movie</a>
</p>
如您先前所見,ASP.NET 將運算子解譯 ~
為網站的根目錄。 您不需要使用 ~
運算子;您可以使用標記 <a href="./AddMovie">Add a movie</a>
或其他方法來定義 HTML 瞭解的路徑。 ~
但是當您建立 Razor 頁面的連結時,運算子是很好的一般方法,因為它可讓網站更有彈性,如果您將目前的頁面移至子資料夾,連結仍會移至AddMovie頁面。 (請記住, ~
運算子只能在 .cshtml 頁面中運作。ASP.NET 瞭解它,但不是標準的 HTML.)
當您完成時,請執行 Movies 頁面。 此頁面看起來會像這樣:
按一下 [ 新增電影 ] 連結,確定該連結會移至 AddMovie 頁面。
即將推出下一個
在下一個教學課程中,您將瞭解如何讓使用者編輯資料庫中已有的資料。
AddMovie 頁面的完整清單
@{
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
var title = "";
var genre = "";
var year = "";
if(IsPost && Validation.IsValid()){
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);
Response.Redirect("~/Movies");
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
<style type="text/css">
.field-validation-error {
font-weight:bold;
color:red;
background-color:yellow;
}
.validation-summary-errors{
border:2px dashed red;
color:red;
background-color:yellow;
font-weight:bold;
margin:12px;
}
</style>
</head>
<body>
<h1>Add 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="@Request.Form["title"]" />
@Html.ValidationMessage("title")
</p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@Request.Form["genre"]" />
@Html.ValidationMessage("genre")
</p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@Request.Form["year"]" />
@Html.ValidationMessage("year")
</p>
<p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
</fieldset>
</form>
</body>
</html>
其他資源
- 使用 Razor 語法進行 ASP.NET 網頁程式設計簡介
- W3Schools 網站上的SQL INSERT INTO 語句
- 驗證 ASP.NET Web Pages網站中的使用者輸入。 使用
Validation
協助程式的詳細資訊。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應