ASP.NET 網頁簡介 - HTML 表單基本概念
本教學課程說明如何建立輸入表單的基本概念,以及如何在使用 ASP.NET 網頁 (Razor) 時處理使用者的輸入。 現在您已擁有資料庫,您將使用表單技能讓使用者在資料庫中尋找特定電影。 本課程假設您已完成使用 ASP.NET 網頁顯示資料簡介系列。
您將學到什麼:
- 如何使用標準 HTML 元素建立表單。
- 如何讀取表單中的使用者輸入。
- 如何用使用者提供的搜尋字詞,建立選擇性地取得資料的 SQL 查詢。
- 如何讓頁面的欄位「記住」使用者輸入的內容。
討論的功能/技術:
Request
物件。- The SQL
Where
子句。
建置內容
在上一個教學課程中,您已建立資料庫、新增資料,然後使用 WebGrid
協助程式來顯示資料。 在本教學課程中,您將新增搜尋方塊,讓您找到特定內容類型的影片,或包含您輸入任何單字的標題。 (例如,您將能夠找到所有內容類型是「動作」或標題包含「哈利」或「冒險」的電影。)
完成本教學課程後,您將會有如下的頁面:
頁面的清單部分與上一個教學課程中的清單部分相同:方格。 差別在於方格只會顯示您搜尋的電影。
關於 HTML 表單
(如果您有建立 HTML 表單的經驗,以及了解 GET
和 POST
的差異,您可以略過本節。)
表單擁有使用者輸入元素:文字方塊、按鈕、單選按鈕、複選方塊、下拉式清單等等。 使用者填寫這些控制項或進行選取,然後按下按鈕以提交表單。
此範例說明表單的基本 HTML 語法:
<form method="post">
<input type="text" name="name" value="" />
<br/>
<input type="submit" name="submit" value="Submit" />
</form>
當此標記在頁面中執行時,它會建立看起來像此圖例的簡單表單:
<form>
元素會封裝要提交的 HTML 元素。 (簡單的錯誤包含將元素新增至頁面,但忘記將它們放在 <form>
元素內。在此案例下,不會提交任何專案)。method
屬性會告知瀏覽器如何提交使用者輸入。 如果您要在伺服器上執行更新,請將此值設定為 post
或如果您只是要從伺服器擷取資料,則設定為 get
。
提示
GET、POST 和 HTTP 動詞安全性
HTTP 為瀏覽器和伺服器用來交換資訊的通訊協定,在其基本作業中相當簡單。 瀏覽器只會使用一些動詞來向伺服器提出要求。 當您撰寫網頁程式碼時,瞭解這些動詞以及瀏覽器和伺服器如何使用它們會很有幫助。 基本上,最常用的動詞如下:
GET
. 瀏覽器會使用此動詞從伺服器擷取專案。 例如,當您在瀏覽器中輸入 URL 時,瀏覽器會執行GET
作業來要求您想要的頁面。 如果頁面包含圖形,瀏覽器會執行其他GET
作業來取得影像。 如果GET
作業必須將資訊傳遞至伺服器,則會在查詢字串中傳遞資訊做為 URL 的一部分。POST
. 瀏覽器會傳送POST
要求,以提交伺服器上要新增或變更的資料。 例如,POST
動詞是用來在資料庫中建立記錄,或變更現有的記錄。 大部分時候,當您填寫表單並按下 [提交] 按鈕時,瀏覽器會執行POST
作業。 在POST
作業中,傳遞至伺服器的資料位於頁面本文中。
這些動詞之間的重要區別在於 GET
作業不應該變更伺服器上的任何項目,或以稍微抽象的方式解釋,即 GET
作業不會造成伺服器上的狀態變更。 您可以視需要對相同資源執行 GET
作業多次,而這些資源不會變更。 (通常 GET
作業算是「安全」的,或使用術語就是 等冪)。相反地,POST
要求會在每次您執行作業時,都會變更伺服器上的某個項目。
兩個範例有助於說明此差異。 當您使用 Bing 或 Google 之類的引擎執行搜尋時,您填寫包含一個文字方塊的表單,然後按下搜尋按鈕。 瀏覽器會執行 GET
作業,並將您輸入方塊的值做為 URL 一部份傳遞。 針對這種類型的表單使用 GET
作業沒問題,因為搜尋作業不會變更伺服器上的任何資源,它只會擷取資訊。
現在,請考慮線上訂購某個物品的過程。 您填寫訂單詳細資料,然後按下提交按鈕。 這項作業將會是 POST
要求,因為作業會導致伺服器上的變更,例如新訂單記錄、您的帳戶資訊變更,又或者許多其他變更。 不同於 GET
作業,您無法重複您的 POST
要求,如果您這樣做,每次重新提交要求時,就會在伺服器上產生新的訂單。 (在這種情況下,網站通常會警告您不要多次按下提交按鈕,或停用提交按鈕,以免意外再次提交表單。)
在本教學課程中,您將同時使用 GET
作業和 POST
作業來處理 HTML 表單。 我們會在每個案例中說明您使用的動詞為何是適當的動詞。
(若要深入瞭解 HTTP 動詞,請參閱W3C 網站上的方法定義文章。)
大部分的使用者輸入元素都是 HTML <input>
元素。 看起來就像 <input type="type" name="name">,
,其中 type 表示您要的使用者輸入控制項類型。 這些元素是常見的:
- 文字方塊:
<input type="text">
- 核取方塊:
<input type="check">
- 單選按鈕:
<input type="radio">
- 按鈕:
<input type="button">
- 提交按鈕:
<input type="submit">
您也可以使用 <textarea>
元素來建立多行文字方塊,也可使用 <select>
元素建立下拉式清單或可捲動的清單。 (如需 HTML 表單元素的詳細資訊,請參閱W3Schools 網站上的 HTML 表單和輸入。)
name
屬性非常重要,因為名稱是您稍後取得元素值的方式,您很快就會了解。
有趣的部分是神為頁面開發人員的您對使用者輸入所執行的動作。 沒有與這些元素相關聯的內建行為。 相反地,您必須取得使用者已輸入或選取的值,並使用它們執行某些動作。 這就是您將在本教學課程中學到的內容。
提示
HTML5 和輸入表單
如您所知,HTML 目前正在變革,而最新版本 (HTML5) 包含對使用者輸入資訊提供更直覺方式的支援。 例如,在 HTML5 中,您 (頁面開發人員) 可以告訴頁面您想要使用者輸入日期。 然後瀏覽器可以自動顯示行事曆,而不需要使用者手動輸入日期。 不過,HTML5 是新的,而且並非所有瀏覽器均支援。
ASP.NET 網頁支援 HTML5 輸入到使用者瀏覽器的範圍。 如需 HTML5 中 <input>
元素新屬性的資訊,請參閱 W3Schools 網站上的 HTML <input> 類型 屬性。
建立表單
在 WebMatrix 的 [檔案] 工作區中,開啟 Movies.cshtml 頁面。
在 grid.GetHtml
呼叫的結尾 </h1>
標籤之後和開頭 <div>
標籤之前,新增下列標記:
<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre" value="" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>
</form>
此標記會建立一個表單,其中包含名為 searchGenre
的文字方塊和提交按鈕。 文字方塊和提交按鈕會封裝在 method
屬性設定為 get
的 <form>
元素中。 (請記住,如果您未將文字方塊和提交按鈕放在 <form>
元素內,則當您按下按鈕時,將不會提交任何項目)。您可以使用這裡的 GET
動詞,因為您正在建立的表單不會在伺服器上進行任何變更,只會產生搜尋結果。 (在上一個教學課程中,您已使用 post
方法,也就是將變更提交至伺服器的方式。您也會在下一個教學課程中看到。)
執行頁面。 雖然您尚未定義表單的任何行為,您可以看到其外觀:
在文字方塊中輸入值,例如「喜劇」。然後按一下 [搜尋內容類型]。
記下頁面的 URL。 由於您已將 <form>
元素的 method
屬性設定為 get
,因此您輸入的值現在是 URL 中查詢字串的一部分,如下所示:
http://localhost:45661/Movies.cshtml?searchGenre=Comedy
讀取表單值
頁面已經包含一些程式碼,可取得資料庫資料,並在方格中顯示結果。 現在,您必須新增一些程式碼來讀取文字方塊的值,以便執行包含搜尋字詞的 SQL 查詢。
由於您將表單的方法設定為 get
,因此您可以使用下列所示的程式碼,讀取在文字方塊中輸入的值:
var searchTerm = Request.QueryString["searchGenre"];
Request.QueryString
物件 (Request
物件的 QueryString
屬性) 包含做為 GET
作業的一部份提交的元素值。 Request.QueryString
屬性包含表單中提交值的 集合 (清單)。 若要取得任何個別值,您可以指定您想要的元素名稱。 這就是為什麼您必須在建立文字方塊的 <input>
元素 (searchTerm
) 上擁有 name
屬性。 (如需 Request
物件的詳細資訊,請參閱稍後的提要欄位。)
光是讀取文字方塊的值就夠簡單了。 但是,如果使用者未在文字方塊中輸入任何內容,但還是按下 [搜尋],則您可以忽略該按下的動作,因為沒有任何可搜尋的內容。
下列程式碼是示範如何實作這些條件的範例。 (您還不需要新增此程式碼,您稍後就會執行此動作。)
if(!Request.QueryString["searchGenre"].IsEmpty() ) {
// Do something here
}
測試會以這種方式細分:
- 取得
Request.QueryString["searchGenre"]
的值,也就是在名為searchGenre
的<input>
元素中輸入的值。 - 使用
IsEmpty
方法找出其是否為空白。 此方法是判斷某個項目 (例如表單元素) 是否包含值的標準方式。 但真的,只有在非空白時才需要處理,因此... - 在
IsEmpty
測試前面新增!
運算子。 (!
運算子表示邏輯 NOT)。
用白話文解釋的話,整個 if
條件會轉譯成下列內容:若表單的 searchGenre 元素不是空白的,則...
此區塊會為建立使用搜尋字詞的查詢設定階段。 您將在下一節中執行該動作。
提示
Request 物件
Request
物件包含在要求或提交頁面時,瀏覽器傳送給您應用程式的所有資訊。 此物件包含使用者提供的任何資訊,例如文字方塊值或要上傳的檔案。 它也包含各種其他資訊,例如 cookies、URL 查詢字串中的值 (若有)、正在執行的頁面檔案路徑、使用者所使用的瀏覽器類型、瀏覽器中所設定的語言清單等更多。
Request
物件是值的集合 (清單)。 您可以藉由指定其名稱,從集合中取得個別值:
var someValue = Request["name"];
Request
物件實際上會公開數個子集。 例如:
- 如果要求是
POST
要求,則Request.Form
會提供來自所提交<form>
元素內的元素值。 Request.QueryString
只提供 URL 查詢字串中的值。 (在類似http://mysite/myapp/page?searchGenre=action&page=2
的 URL 中,URL 的?searchGenre=action&page=2
區段是查詢字串。)Request.Cookies
集合可讓您存取瀏覽器已傳送的 cookies。
若要取得您知道的是在提交表單中的值,您可以使用 Request["name"]
。 或者,您可以使用更具體的版本 Request.Form["name"]
(若為 POST
要求) 或 Request.QueryString["name"]
(若為 GET
要求)。 當然,name 是要取得的項目名稱。
您想要取得的項目名稱在您使用的集合中必須是唯一的。 這就是為什麼 Request
物件提供如 Request.Form
和 Request.QueryString
子集的原因。 假設您的頁面包含名為 userName
的表單元素,而且包含名為 userName
的 cookie。 如果您取得 Request["userName"]
,則您想要表單值還是 cookie 會難以辨別。 不過,如果您取得 Request.Form["userName"]
或 Request.Cookie["userName"]
,則您是明確指出要取得的值。
最好練習明確性,並使用您感興趣的 Request
子集,例如 Request.Form
或 Request.QueryString
。 針對您在本教學課程中建立的簡單頁面,它可能不會真的有任何差異。 不過,當您建立更複雜的頁面時,使用明確版本 Request.Form
或 Request.QueryString
可在頁面包含表單 (或多個表單)、cookies、查詢字串值等時,協助您避免可能發生的問題。
使用搜尋字詞建立查詢
既然您已瞭解如何取得使用者輸入的搜尋字詞,您可以建立使用該字詞的查詢。 請記住,若要從資料庫中取得所有電影項目,您要使用類似下列陳述式的 SQL 查詢:
SELECT * FROM Movies
若要只取得特定電影,您必須使用包含 Where
子句的查詢。 這個子句可讓您設定由查詢傳回資料列的條件。 以下是範例:
SELECT * FROM Movies WHERE Genre = 'Action'
基本格式為 WHERE column = value
。 您可以使用除了 =
以外的不同運算子,如:>
(大於)、<
(小於)、<>
(不等於)、<=
(小於或等於) 等,取決於您想查找的內容。
提醒您,SQL 陳述式不區分大小寫 SELECT
相同於 Select
(或甚至是 select
)。 不過,人們通常會在 SQL 陳述式中大寫關鍵詞,例如 SELECT
和 WHERE
,以便更容易閱讀。
將搜尋字詞當做參數傳遞
搜尋特定內容類型很簡單 (WHERE Genre = 'Action'
),但您想要能夠搜尋使用者輸入的任何內容類型。 若要這樣做,您可以建立為 SQL 查詢,其中包含要搜尋值的預留位置。 看起來像下列指令:
SELECT * FROM Movies WHERE Genre = @0
預留位置是後面接著零的 @
字元。 如您所猜測,查詢可以包含多個預留位置,且其名為 @0
、@1
、@2
等。
若要設定查詢並實際傳遞該值,您可以使用如下程式碼:
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
selectedData = db.Query(selectCommand, Request.QueryString["searchGenre"]);
此程式碼類似於您已經在方格中執行以顯示資料的動作。 唯一差異是:
- 查詢包含預留位置 (
WHERE Genre = @0"
)。 - 會將查詢放入變數中 (
selectCommand
),之前,您直接將查詢傳遞至db.Query
方法。 - 當您呼叫
db.Query
方法時,您會同時傳遞查詢和要用於預留位置的值。 (如果查詢有多個預留位置,您會將它們全部當作個別的值傳遞給方法。)
如果您將所有元素放在一起,您會得到下列程式碼:
if(!Request.QueryString["searchGenre"].IsEmpty() ) {
searchTerm = Request.QueryString["searchGenre"];
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
selectedData = db.Query(selectCommand, searchTerm);
}
注意
重要! 使用預留位置 (例如 @0
) 將值傳遞至 SQL 命令對於安全性而言非常重要。 您在這裡看到的方法是使用變數資料的預留位置,是建構 SQL 命令的唯一方式。
務必不要藉由結合 (串連) 常值文字和您從使用者取得的值來建構 SQL 陳述式。 將使用者輸入串連至 SQL 陳述式,會將您的網站開放接受 SQL 插入式攻擊,即惡意使用者將值提交至您的頁面以破解您的資料庫。 (您可以在 MSDN 網站上的文章 SQL 插入閱讀更多內容。)
使用搜尋程式碼更新電影頁面
現在,您可以在 Movies.cshtml 檔案中更新程式碼。 若要開始,請使用下列程式碼取代頁面頂端程式碼區塊中的程式碼:
var db = Database.Open("WebPagesMovies");
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";
此處的差異在於您已將查詢放入 selectCommand
變數中,稍後會傳遞至 db.Query
。 將 SQL 陳述式放入變數可讓您變更陳述式,也就是您將執行的搜尋作業。
您也要移除這兩行,稍後再放回:
var selectedData = db.Query("SELECT * FROM Movies");
var grid = new WebGrid(source: selectedData, rowsPerPage: 3);
您還不想執行查詢 (也就是呼叫 db.Query
),您也不想初始化 WebGrid
協助程式。 在您找出哪些 SQL 陳述式必須執行之後,您將會執行這些動作。
在此重寫區塊之後,您可以新增處理搜尋的新邏輯。 完整的程式碼看起來如下列。 更新頁面中的程式碼,使其符合此範例:
@{
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"];
}
var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}
頁面現在會像這樣運作。 每次執行頁面時,程式碼都會開啟資料庫,並將 selectCommand
變數設定為 SQL 陳述式,以從 Movies
資料表取得所有記錄。 程式碼也會初始化 searchTerm
變數。
不過,如果目前的要求包含 searchGenre
元素的值,程式碼就會將 selectCommand
設定為不同的查詢,也就是設定為包含要搜尋內容類型的 Where
子句。 它也會將 searchTerm
設定為搜尋方塊所傳遞的任何內容 (可能沒有任何內容)。
不論 selectCommand
中是哪一個 SQL 陳述式,程式碼接著會呼叫 db.Query
來執行查詢,並傳遞 searchTerm
中的任何內容。 如果 searchTerm
中沒有任何內容,也沒關係,因為在此案例下,沒有任何參數可將值傳遞至 selectCommand
。
最後,程式碼會使用查詢結果來初始化 WebGrid
協助程式,就像之前一樣。
您可以藉由將 SQL 陳述式和搜尋字詞放入變數中,為程式碼增加彈性。 如您稍後在本教學課程中所見,您可以使用這個基本架構,持續新增不同類型的搜尋邏輯。
測試依內容類型搜尋功能
在 WebMatrix 中,執行 Movies.cshtml 頁面。 您會看到具有內容類型文字方塊的頁面。
輸入您針對其中一筆測試記錄輸入的內容類型,然後按一下 [搜尋]。 這次您只會看到符合該內容類型的電影清單:
輸入不同的內容類型,然後再次搜尋。 請嘗試使用全部小寫或全部大寫字母來輸入內容類型,讓您可以看到搜尋是不區分大小寫的。
「記住」使用者輸入的內容
您可能已經注意到,在您輸入內容類型並按一下 [搜尋內容類型] 之後,您會看到該內容類型的清單。 不過,搜尋文字方塊是空的,換句話說,它不記得您輸入的內容。
請務必瞭解此行為發生的原因。 當您提交頁面時,瀏覽器會將要求傳送至網頁伺服器。 當 ASP.NET 取得要求時,它會建立全新的頁面執行個體,在其中執行程式碼,然後再次將頁面轉譯至瀏覽器。 不過,實際上,頁面並不知道您是使用其舊版。 它知道的是它得到了一個要求,其中包含一些表單資料。
每次您要求頁面時,無論是第一次還是提交頁面,您都會收到新的頁面。 網頁伺服器不記得上一次的要求。 ASP.NET 也沒有,瀏覽器也沒有。 頁面的這些個別執行個體之間唯一的連接,就是您在它們之間傳輸的任何資料。 例如,若您提交頁面,新的頁面執行個體可以取得先前執行個體所傳送的表單資料。 (在頁面之間傳遞資料的另一種方式是使用 cookies。)
描述這種情況的正式方式是說網頁為無狀態。 網頁伺服器和頁面本身,以及頁面中的元素不會保留頁面先前狀態的任何資訊。 網頁的設計方式是這樣,因為保留個別要求的狀態會很快耗盡網頁伺服器的資源,而網頁伺服器通常每秒處理數千個甚至數十萬個要求。
因此,文字方塊是空的。 提交頁面之後,ASP.NET 建立頁面的新執行個體,並執行程式碼和標記。 該程式碼中沒有任何內容告訴 ASP.NET 將值放入文字方塊中。 因此,ASP.NET 沒有執行任何動作,而且文字方塊在沒有值的情況下轉譯。
實際上有一個簡單的方法來解決此問題。 您在文字方塊中輸入的內容類型可在程式碼中使用,其位於 Request.QueryString["searchGenre"]
中。
更新文字方塊的標記,讓 value
屬性能從 searchTerm
取得其值,如下列範例所示:
<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
在此頁面中,您也可以將 value
屬性設定為 searchTerm
變數,因為該變數也包含您輸入的內容類型。 但是如下所示使用 Request
物件來設定 value
屬性是完成這項工作的標準方式。 (假設您甚至想要這樣做,在某些情況下,您可能會想要轉譯頁面,而欄位中沒有值。這一切都取決於您的應用程式的執行內容。)
注意
您無法「記住」用於密碼的文字方塊值。 這是一個安全性漏洞,允許人們使用程式碼填入密碼欄位。
再次執行頁面,輸入內容類型,然後按一下 [搜尋內容類型]。 這次您不僅會看到搜尋的結果,而且文字方塊會記住您上次輸入的內容:
搜尋標題中的任何單字
您現在可以搜尋任何內容類型,但您可能也想要搜尋標題。 當您搜尋時,很難正確地提供完整標題,因此您可以搜尋在標題內任何位置上出現的文字。 若要在 SQL 中執行此動作,請使用 LIKE
運算子和語法,如下所示:
SELECT * FROM Movies WHERE Title LIKE '%adventure%'
此命令會取得標題包含「冒險」的所有電影。 當您使用 LIKE
運算子時,您會在搜尋字詞中包含萬用字元 %
。 搜尋 LIKE 'adventure%'
表示「以『adventure』開頭」。 (從技術上而言,這意味著「字串『adventure』後面可接任何內容。」) 同樣地,搜尋字詞 LIKE '%adventure'
表示「字串『adventure』前可以是任何內容」,這是「以『adventure』結尾」的另一種表示方式。
因此,搜尋字詞 LIKE '%adventure%'
表示「在標題中的任何位置含有『adventure』」。(從技術上尚而言「標題中的任何內容,接著『adventure』,後接任何內容。」)
在 <form>
元素內的內容類型搜尋的結尾 </div>
標籤底下新增下列標記 (就在結尾 </form>
元素之前):
<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>
處理此搜尋的程式碼類似於內容類型搜尋用的程式碼,但您必須組合 LIKE
搜尋。 在頁面頂端的程式碼區塊內,就在內容類型搜尋的 if
區塊之後新增此 if
區塊:
if(!Request.QueryString["searchTitle"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
searchTerm = "%" + Request["searchTitle"] + "%";
}
此程式碼會使用您稍早看到的相同邏輯,不同之處在於搜尋會使用 LIKE
運算子,而程式碼會在搜尋字詞前後放置「%
」。
請注意,將另一個搜尋新增至頁面是多麼容易。 您必須做的就是:
- 建立經過測試以查看相關搜尋方塊是否有值的
if
區塊。 - 將
selectCommand
變數設定為新的 SQL 陳述式。 - 將
searchTerm
變數設定為要傳遞至查詢的值。
以下是完整的程式碼區塊,其中包含用於標題搜尋的新邏輯:
@{
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["searchTitle"] + "%";
}
var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:8);
}
以下是此程式碼的功能摘要:
- 變數
searchTerm
和selectCommand
會在頂端初始化。 您將根據使用者在頁面中執行的動作,將這些變數設定為適當的搜尋字詞 (若有) 和適當的 SQL 命令。 預設搜尋是從資料庫取得所有電影的簡單案例。 - 在用於
searchGenre
和searchTitle
的測試中,程式碼會將searchTerm
設定為您要搜尋的值。 這些程式碼區塊也會將selectCommand
設定為適合該搜尋的 SQL 命令。 db.Query
方法只會叫用一次,使用在selectedCommand
中的任何 SQL 命令,以及searchTerm
中的任何值。 如果沒有搜尋字詞 (沒有內容類型和標題字),則searchTerm
的值是空字串。 不過,這並不重要,因為在此案例下,查詢不需要參數。
測試標題搜尋功能
現在您可以測試已完成的搜尋頁面。 執行 Movies.cshtml。
輸入內容類型,然後按一下 [搜尋內容類型]。 方格會顯示該內容類型的電影,就如之前所示。
輸入標題字,然後按一下 [搜尋標題]。 方格會顯示標題中有該字的電影。
將這兩個文字方塊保留空白,然後按一下任一按鈕。 方格會顯示所有電影。
結合查詢
您可能會注意到您可以執行的搜尋是有排他性的。 即使這兩個搜尋方塊內都有值,您也無法同時搜尋標題和內容類型。 例如,您無法搜尋標題包含「冒險」的所有動作電影。 (由於頁面現在已經過程式編碼,如果您同時輸入內容類型和標題的值,標題搜尋會優先)。若要建立結合條件的搜尋,您必須建立具有類似下列語法的 SQL 查詢:
SELECT * FROM Movies WHERE Genre = @0 AND Title LIKE @1
您必須使用如下的陳述式來執行查詢 (大致來說):
var selectedData = db.Query(selectCommand, searchGenre, searchTitle);
建立邏輯以允許許多搜尋準則排列可能需要多花點心思,正如您所見。 因此,我們將在這裡停下。
接續內容
在下一個教學課程中,您將建立一個頁面,該頁面會使用表單讓使用者將電影新增至資料庫。
電影頁面的完整清單 (已更新搜尋)
@{
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["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("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
</div>
</body>
</html>
其他資源
- 使用 Razor 語法進行 ASP.NET 網頁程式設計簡介
- W3Schools 網站上的 SQL WHERE 子句
- W3C 網站上的方法定義 文章