if(!Request.QueryString["searchGenre"].IsEmpty() ) {
// Do something here
测试以这种方式分解:
获取 的值Request.QueryString["searchGenre"]
,即在名为 searchGenre
的元素中<input>
输入的值。
使用 IsEmpty
方法找出它是否为空。 此方法是确定某些 ((例如,窗体元素) 是否包含值)的标准方法。 但真的,你只关心它 不是 空的,因此...
在 !
测试前面 IsEmpty
添加 运算符。 (运算符 !
表示逻辑 NOT) 。
在纯英语中,整个 if
条件将转换为以下内容: 如果窗体的 searchGenre 元素不为空,则...
此块设置创建使用搜索词的查询的阶段。 将在下一部分执行该操作。
Request 对象
对象 Request
包含请求或提交页面时浏览器发送给应用程序的所有信息。 此对象包括用户提供的任何信息,例如文本框值或要上传的文件。 它还包括各种附加信息,如 Cookie、URL 查询字符串 ((如果有任何) )中的值、正在运行的页面的文件路径、用户使用的浏览器类型、在浏览器中设置的语言列表等。
对象 Request
是值的 集合 (列表) 。 通过指定其名称,从集合中获取单个值:
var someValue = Request["name"];
对象 Request
实际上公开了多个子集。 例如:
Request.Form
如果请求是POST
请求,则从提交的<form>
元素内的元素中提供值。
Request.QueryString
仅提供 URL 的查询字符串中的值。 (在类似于 的 http://mysite/myapp/page?searchGenre=action&page=2
URL 中, ?searchGenre=action&page=2
URL 的 节是查询字符串。)
Request.Cookies
集合使你能够访问浏览器发送的 Cookie。
若要获取已知位于已提交的表单中的值,可以使用 Request["name"]
。 或者,可以将更具体的版本 Request.Form["name"]
(用于 POST
请求) 或 Request.QueryString["name"]
(GET
) 的请求。 当然, name 是要获取的项的名称。
要获取的项的名称在所使用的集合中必须是唯一的。 这就是为什么 对象提供 和 等Request.Form
Request.QueryString
子集的原因Request
。 假设页面包含名为 的 userName
表单元素, 并且还 包含名为 的 userName
Cookie。 如果获得 Request["userName"]
,则不明确是要窗体值还是 Cookie。 但是,如果获取 Request.Form["userName"]
或 Request.Cookie["userName"]
,则明确表示要获取哪个值。
最好是具体化并使用你感兴趣的 子 Request
集,例如 Request.Form
或 Request.QueryString
。 对于在本教程中创建的简单页面,它可能没有任何区别。 但是,在创建更复杂的页面时,使用显式版本 Request.Form
或 Request.QueryString
有助于避免页面包含表单 (或多个窗体) 、Cookie、查询字符串值等时可能出现的问题。
使用搜索词创建查询
了解如何获取用户输入的搜索词后,可以创建使用该搜索词的查询。 请记住,若要从数据库中获取所有电影项,将使用类似于以下语句的 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
方法时,将同时传递查询和要用于占位符的值。 (如果查询有多个占位符,则将它们作为单独的值传递给 method.)
如果将所有这些元素放在一起,将获得以下代码:
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 页。 你将看到包含“流派”文本框的页面。
输入已为其中一个测试记录输入的流派,然后单击“ 搜索”。 这一次,你只看到与该流派匹配的电影列表:
输入其他流派并再次搜索。 尝试使用所有小写字母或全大写字母进入流派,以便可以看到搜索不区分大小写。
“记住”用户输入的内容
你可能已注意到,在输入流派并单击“ 搜索流派”后,会看到该流派的列表。 但是,搜索文本框为空,换句话说,它不记得你输入的内容。
请务必了解发生此行为的原因。 提交页面时,浏览器会向 Web 服务器发送请求。 当 ASP.NET 获取请求时,它会创建页面的全新实例,运行其中的代码,然后再次将页面呈现到浏览器。 但实际上,页面并不知道你只是使用以前的版本本身。 它只知道它收到了一个请求,其中包含一些表单数据。
每次请求页面(无论是第一次还是通过提交页面)时,你都会获得一个新页面。 Web 服务器没有上次请求的内存。 ASP.NET,浏览器也不 ASP.NET。 页面的这些独立实例之间的唯一连接是你在它们之间传输的任何数据。 例如,如果提交页面,则新页面实例可以获取先前实例发送的表单数据。 (在页面之间传递数据的另一种方法是使用 cookies.)
描述这种情况的正式方法是说网页是 无状态的。 Web 服务器和页面本身以及页面中的元素不维护有关页面先前状态的任何信息。 Web 是这样设计的,因为维护单个请求的状态会迅速耗尽 Web 服务器的资源,后者通常每秒处理数千个甚至数十万个请求。
因此,文本框为空。 提交页面后,ASP.NET 创建了页面的新实例,并运行代码和标记。 该代码中没有任何内容告知 ASP.NET 将值放入文本框中。 因此,ASP.NET 未执行任何操作,并且文本框呈现时没有值。
实际上有一种简单的方法来解决此问题。 在代码 中,可在 文本框中输入的流派 - 它位于 中 Request.QueryString["searchGenre"]
。
更新文本框的标记,使 value
特性从 searchTerm
获取其值,如以下示例:
<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
在此页中,还可以将 属性设置为 value
searchTerm
变量,因为该变量还包含你输入的流派。 但是, Request
使用 对象设置 属性, value
如下所示是完成此任务的标准方法。 (假设你甚至想要执行此操作 -在某些情况下,你可能想要呈现页面, 而不 在字段中显示值。这完全取决于应用的情况。)
无法“记住”用于密码的文本框的值。 允许用户使用代码填写密码字段将是一个安全漏洞。
再次运行页面,输入流派,然后单击“ 搜索流派”。 这一次,你不仅会看到搜索结果,而且文本框会记住上次输入的内容:
在游戏中搜索任何Word
现在可以搜索任何流派,但可能还需要搜索标题。 搜索时很难完全正确获取标题,因此可以搜索标题内任何位置显示的单词。 若要在 SQL 中执行此操作,请使用 LIKE
运算符和语法,如下所示:
SELECT * FROM Movies WHERE Title LIKE '%adventure%'
此命令获取其标题包含“adventure”的所有电影。 使用 LIKE
运算符时,可以在搜索词中包含通配符 %
。 搜索 LIKE 'adventure%'
意味着“从'adventure'开始”。 (技术上,它意味着“字符串'adventure'后跟任何内容”。) 同样,搜索词 LIKE '%adventure'
表示“任何内容后跟字符串'adventure'”,这是另一种表示“以'adventure'结尾”的方式。
因此,搜索词 LIKE '%adventure%'
的意思是“具有'adventure'在标题中的任何位置。” (技术上,“标题中的任何内容,后跟'adventure',后跟任何内容。)
在 元素内<form>
,紧跟在结束元素 (的结束标记 (的结束</div>
</form>
标记下添加以下标记) :
<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/>
处理此搜索的代码类似于流派搜索的代码,但必须组合 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 命令。 默认搜索是从数据库获取所有电影的简单情况。
在 和 searchTitle
的测试searchGenre
中,代码将设置为searchTerm
要搜索的值。 这些代码块还设置为 selectCommand
该搜索的相应 SQL 命令。
方法 db.Query
仅调用一次,使用 中 selectedCommand
任何 SQL 命令以及 中 searchTerm
的任何值。 如果没有搜索词 (没有流派,也没有标题词) ,则 的值 searchTerm
是空字符串。 但是,这并不重要,因为在这种情况下,查询不需要参数。
测试标题搜索功能
现在可以测试已完成的搜索页面。 运行 Movies.cshtml。
输入流派并单击“ 搜索流派”。 网格显示该流派的电影,就像以前一样。
输入标题词,然后单击“ 搜索标题”。 网格显示标题中具有该单词的电影。
将两个文本框留空,然后单击任一按钮。 网格显示所有电影。
你可能会注意到,可以执行的搜索是独占的。 不能同时搜索标题和流派,即使两个搜索框中都有值。 例如,无法搜索标题包含“Adventure”的所有动作电影。 (现在对页面进行编码时,如果同时输入流派和标题的值,则标题搜索将优先。) 若要创建组合条件的搜索,则必须创建具有以下语法的 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">
<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>
<h1>Movies</h1>
<form method="get">
<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/>
<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/>
</form>
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
</body>
</html>
使用 Razor 语法进行 ASP.NET Web 编程简介
W3Schools 网站上的 SQL WHERE 子句
W3C 网站上的方法定义一文
上一页下一页