ASP.NET Web ページの概要 - HTML フォームの基本

Tom FitzMacken

このチュートリアルでは、入力フォームを作成する方法の基本と、ASP.NET Web ページ (Razor) を使用するときにユーザーの入力を処理する方法について説明します。 データベースが作成されたので、フォーム スキルを使用して、ユーザーがデータベース内の特定の映画を見つけられるようにします。 ASP.NET Web ページを使用したデータの表示の概要に関するページでシリーズを完了していることを前提としています。

ここでは、次の内容について学習します。

  • 標準の HTML 要素を使用してフォームを作成する方法。
  • フォームでユーザーの入力を読み取る方法。
  • ユーザーが提供する検索用語を使用してデータを選択的に取得する SQL クエリを作成する方法。
  • ユーザーが入力した内容を "記憶" するページ内のフィールドを設定する方法。

説明した機能/テクノロジ:

  • Request オブジェクト。
  • SQL Where 句。

作成するアプリケーション:

前のチュートリアルでは、データベースを作成し、それにデータを追加した後、ヘルパーを WebGrid 使用してデータを表示しました。 このチュートリアルでは、特定のジャンルの映画を検索したり、タイトルに入力した単語が含まれている検索ボックスを追加します。 (たとえば、ジャンルが "Action" であるか、タイトルに "Harry" または "Adventure" が含まれているすべての映画を見つけることができます)。

このチュートリアルを完了すると、次のようなページが表示されます。

ジャンルとタイトル検索を含む [ムービー] ページ

ページの一覧部分は、最後のチュートリアル (グリッド) と同じです。 違いは、検索したムービーのみがグリッドに表示されることです。

HTML フォームについて

(HTML フォームの作成の経験があり、 と POSTの違いGETがある場合は、このセクションをスキップできます)。

フォームには、テキスト ボックス、ボタン、ラジオ ボタン、チェック ボックス、ドロップダウン リストなどのユーザー入力要素があります。 ユーザーはこれらのコントロールに入力するか、選択を行い、ボタンをクリックしてフォームを送信します。

フォームの基本的な HTML 構文を次の例に示します。

<form method="post">
  <input type="text" name="name" value="" />
  <br/>
  <input type="submit" name="submit" value="Submit" />
</form>

このマークアップをページで実行すると、次の図のような単純なフォームが作成されます。

ブラウザーでレンダリングされる基本的な HTML フォーム

要素は <form> 、送信する HTML 要素を囲みます。 (簡単な間違いは、ページに要素を追加してから、要素内 <form> に配置するのを忘れることです。その場合、何も送信されません。属性は method 、ユーザー入力を送信する方法をブラウザーに指示します。 サーバー post で更新を実行する場合は に、サーバーからデータをフェッチする場合は を に get 設定します。

ヒント

GET、POST、HTTP 動詞の安全性

ブラウザーとサーバーが情報を交換するために使用するプロトコルである HTTP は、基本的な操作で非常に簡単です。 ブラウザーでは、サーバーへの要求を行うために使用する動詞はごくわずかです。 Web 用のコードを記述するときは、これらの動詞と、ブラウザーとサーバーでこれらの動詞がどのように使用されるかを理解しておくと役立ちます。 最も一般的に使用される動詞は、遠く離れたところに次のとおりです。

  • GET. ブラウザーでは、この動詞を使用してサーバーから何かをフェッチします。 たとえば、ブラウザーに URL を入力すると、ブラウザーは目的のページを GET 要求する操作を実行します。 ページにグラフィックスが含まれている場合、ブラウザーは画像を取得するための追加 GET の操作を実行します。 操作で GET サーバーに情報を渡す必要がある場合、情報はクエリ文字列の URL の一部として渡されます。
  • POST. サーバーに追加または変更するデータを送信するために、ブラウザーから要求が送信 POST されます。 たとえば、動詞は POST 、データベース内にレコードを作成したり、既存のレコードを変更したりするために使用されます。 ほとんどの場合、フォームに入力して [送信] ボタンをクリックすると、ブラウザーで操作が POST 実行されます。 操作では POST 、サーバーに渡されるデータはページの本文にあります。

これらの動詞の重要な違いは GET 、操作がサーバー上で何かを変更することや、 GET 少し抽象的な方法で配置することは想定されていないことです。操作によってサーバーの状態が変化することはありません。 同じリソースに対して何度でも操作を実行 GET できますが、それらのリソースは変更されません。 GET(操作は多くの場合、"安全" と言われるか、技術用語を使用すると、べき等です)。これに対し、要求は、操作をPOST実行するたびにサーバー上で何かを変更します。

2 つの例は、この違いを示すのに役立ちます。 Bingや Google などのエンジンを使用して検索を実行する場合は、1 つのテキスト ボックスで構成されるフォームに入力し、検索ボタンをクリックします。 ブラウザーで操作が GET 実行され、URL の一部としてボックスに入力した値が渡されます。 この種類のフォームに対して操作を GET 使用しても問題ありません。検索操作ではサーバー上のリソースは変更されないため、情報をフェッチするだけです。

次に、オンラインで何かを注文するプロセスを検討します。 注文の詳細を入力し、[送信] ボタンをクリックします。 この操作は、新しい POST 注文レコード、アカウント情報の変更、その他の多くの変更など、サーバー上で変更が発生するため、要求になります。 GET操作とは異なり、要求を繰り返すことはできません。要求をPOST再送信するたびに、サーバーで新しい注文を生成します。 (このような場合、フォームを誤って再送信しないように、送信ボタンを複数回クリックしないように Web サイトから警告されたり、送信ボタンが無効にされたりすることがよくあります)。

このチュートリアルのコースでは、操作とPOST操作の両方をGET使用して HTML フォームを操作します。 それぞれのケースで、使用する動詞が適切な動詞である理由について説明します。

(HTTP 動詞の詳細については、W3C サイトの メソッド定義 に関する記事を参照してください)。

ほとんどのユーザー入力要素は HTML <input> 要素です。 は、目的のユーザー入力コントロールの種類を示す場所のようになります<input type="type" name="name">,。 これらの要素は一般的な要素です。

  • テキスト ボックス: <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 Web ページでは、ユーザーのブラウザーが行う範囲での HTML5 入力がサポートされます。 HTML5 の 要素の新しい属性 <input> については、W3Schools サイトの HTML <入力> 型 Attribute に関するページを参照してください。

フォームの作成

WebMatrix の [ファイル ] ワークスペースで、[ Movies.cshtml ] ページを開きます。

終了 </h1> タグの後、呼び出しの開始 <div> タグの前に grid.GetHtml 、次のマークアップを追加します。

<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 のテキスト ボックスと送信ボタンを含むフォームを作成します。 テキスト ボックスと送信ボタンは、 属性が にget設定されている要素method<form>囲まれています。 (テキスト ボックスと送信ボタンを要素内 <form> に配置しない場合、ボタンをクリックしても何も送信されない点に注意してください)。ここで動詞を GET 使用するのは、サーバー上で変更を加えないフォームを作成しているためです。これは、検索の結果にすぎません。 (前のチュートリアルでは、 メソッドを post 使用しました。これは、サーバーに変更を送信する方法です。これは、次のチュートリアルでもう一度確認できます)。

ページを実行します。 フォームの動作を定義していませんが、次のように表示されます。

ジャンルの検索ボックスが表示された [ムービー] ページ

"Comedy" などの値をテキスト ボックスに入力します。次に、[ 検索ジャンル] をクリックします。

ページの URL を書き留めます。 要素の method 属性を <form>get設定したため、次のように、入力した値が URL のクエリ文字列の一部になりました。

http://localhost:45661/Movies.cshtml?searchGenre=Comedy

フォーム値の読み取り

このページには、データベース データを取得し、結果をグリッドに表示するコードが既に含まれています。 検索語句を含む SQL クエリを実行できるように、テキスト ボックスの値を読み取るコードをいくつか追加する必要があります。

フォームの メソッドを に get設定するため、次のようなコードを使用して、テキスト ボックスに入力された値を読み取ることができます。

var searchTerm = Request.QueryString["searchGenre"];

Request.QueryStringオブジェクト (オブジェクトの QueryStringRequest プロパティ) には、操作の一部として送信された要素の値がGET含まれます。 プロパティには Request.QueryString 、フォームで送信される値の コレクション (リスト) が含まれています。 個々の値を取得するには、目的の要素の名前を指定します。 そのため、テキスト ボックスを作成するname要素 (searchTerm) に<input>属性を設定する必要があります。 (オブジェクトの Request 詳細については、後で サイドバー を参照してください)。

テキスト ボックスの値を読み取るのに十分簡単です。 ただし、ユーザーがテキスト ボックスに何も入力せず、[ 検索 ] をクリックした場合は、検索するものがないため、そのクリックは無視できます。

次のコードは、これらの条件を実装する方法を示す例です。 (このコードを追加する必要はありません。すぐに追加できます)。

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 要求が要求である場合は、送信された <form> 要素内の要素から値が POST 提供されます。
  • Request.QueryString では、URL のクエリ文字列の値だけが提供されます。 (のような http://mysite/myapp/page?searchGenre=action&page=2URL では、URL の ?searchGenre=action&page=2 セクションはクエリ文字列です)。
  • Request.Cookies コレクションを使用すると、ブラウザーが送信した Cookie にアクセスできます。

送信されたフォームにあることがわかっている値を取得するには、 を使用 Request["name"]します。 または、より具体的なバージョン Request.Form["name"] (要求の場合 POST ) または Request.QueryString["name"] ( GET 要求の場合) を使用することもできます。 もちろん、 name は取得するアイテムの名前です。

取得するアイテムの名前は、使用しているコレクション内で一意である必要があります。 そのため、 オブジェクトは RequestRequest.QueryStringなどのRequest.Formサブセットを提供します。 ページに という名前のフォーム要素が含まれており、 というuserName名前userNameの Cookie 含まれているとします。 を取得 Request["userName"]した場合、フォーム値と Cookie のどちらを使用するかはあいまいです。 ただし、 または Request.Cookie["userName"]を取得Request.Form["userName"]する場合は、取得する値を明示的に指定します。

や などRequest.FormRequest.QueryString、関心のある のRequestサブセットを特定して使用することをお勧めします。 このチュートリアルで作成する単純なページでは、実際には違いはありません。 ただし、より複雑なページを作成するときは、明示的なバージョン Request.Form を使用するか、ページ Request.QueryString にフォーム (または複数のフォーム)、Cookie、クエリ文字列値などが含まれている場合に発生する可能性がある問題を回避するのに役立ちます。

検索用語を使用したクエリの作成

ユーザーが入力した検索用語を取得する方法がわかったら、それを使用するクエリを作成できます。 データベースからすべてのムービー アイテムを取得するには、次のステートメントのような SQL クエリを使用します。

SELECT * FROM Movies

特定のムービーのみを取得するには、 句を含む Where クエリを使用する必要があります。 この句を使用すると、クエリによって行が返される条件を設定できます。 次に例を示します。

SELECT * FROM Movies WHERE Genre = 'Action'

基本的な形式は です WHERE column = value。 求めている内容に応じて、(より大きい)、(より小さい) < 、(等しくない) <= 、(以下)など、だけでなく、さまざまな演算子=>を使用 <> できます。

疑問に思う場合、SQL ステートメントでは大文字とSELECT小文字は区別されません。 は と同じです Select (または)。select ただし、多くの場合、ユーザーは、読みやすくするために、 や WHEREなどの SELECT SQL ステートメントのキーワードを大文字にします。

検索用語をパラメーターとして渡す

特定のジャンルの検索は簡単ですが (WHERE Genre = 'Action')、ユーザーが入力した任意のジャンルを検索できるようにする必要があります。 これを行うには、検索する値のプレースホルダーを含む SQL クエリとしてを作成します。 次のコマンドのようになります。

SELECT * FROM Movies WHERE Genre = @0

プレースホルダーは、文字の後に @ 0 が続きます。 ご想像のとおり、クエリには複数のプレースホルダーを含めることができます。また、、@1@2、などの名前が付けられます@0

クエリを設定し、実際に値を渡すには、次のようなコードを使用します。

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);
}

Note

重要: プレースホルダー (など @0) を使用して SQL コマンドに値を渡すことは、セキュリティにとって 非常に重要 です。 ここでは、変数データのプレースホルダーを使用して表示する方法が、SQL コマンドを構築する唯一の方法です。

ユーザーから取得したリテラル テキストと値をまとめ (連結) して、SQL ステートメントを構築しないでください。 ユーザー入力を SQL ステートメントに連結すると、悪意のあるユーザーがデータベースをハッキングする値をページに送信する SQL インジェクション攻撃 にサイトが開きます。 (詳細については、MSDN Web サイトの SQL インジェクション に関する記事を参照してください)。

検索コードを使用してムービー ページを更新する

これで、 Movies.cshtml ファイルのコードを更新できます。 まず、ページの上部にあるコード ブロック内のコードを次のコードに置き換えます。

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

ここでの違いは、後で渡す変数に selectCommand クエリを db.Query 配置したことです。 SQL ステートメントを変数に入れると、 ステートメントを変更できます。これは、検索を実行するために行う操作です。

また、これらの 2 つの行も削除しました。この行は後で元に戻します。

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含まれている場合、コードは別のクエリ (つまり、ジャンルを検索する 句をWhere含むクエリ) に設定selectCommandされます。 また、検索ボックスに渡されたもの (何もない可能性があります) にも設定 searchTerm されます。

に含まれる SQL ステートメントに関係なく、コードは selectCommandを呼び出 db.Query してクエリを実行し、 内 searchTermにあるものを渡します。 に searchTerm何もない場合は、値を渡す selectCommand パラメーターがないため、関係ありません。

最後に、前と同様に WebGrid 、クエリ結果を使用してヘルパーを初期化します。

SQL ステートメントと検索用語を変数に入れることで、コードに柔軟性が追加されていることがわかります。 このチュートリアルの後半で説明するように、この基本的なフレームワークを使用し、さまざまな種類の検索のロジックを追加し続けることができます。

ジャンル別検索機能のテスト

WebMatrix で、 Movies.cshtml ページを 実行します。 ジャンルのテキスト ボックスが表示されたページが表示されます。

いずれかのテスト レコードに入力したジャンルを入力し、[ 検索] をクリックします。 今回は、そのジャンルに一致する映画のみの一覧が表示されます。

ジャンル 'コメディ' を検索した後の映画ページの一覧

別のジャンルを入力して、もう一度検索します。 検索で大文字と小文字が区別されないことを確認できるように、すべて小文字またはすべての大文字を使用してジャンルを入力してみてください。

ユーザーが入力した内容を記憶する

ジャンルを入力して [ 検索ジャンル] をクリックすると、そのジャンルの一覧が表示されていることに気付いたかもしれません。 ただし、検索テキスト ボックスは空でした。つまり、入力した内容を覚えていませんでした。

この動作が発生する理由を理解することが重要です。 ページを送信すると、ブラウザーから Web サーバーに要求が送信されます。 ASP.NET が要求を取得すると、ページのまったく新しいインスタンスが作成され、その中でコードが実行され、ページがブラウザーに再度レンダリングされます。 ただし、実際には、以前のバージョンのそれ自体を操作していただけではページに認識されません。 知っているのは、何らかのフォーム データが含まれる要求を受け取ったことです。

初めてページを要求するたびに、またはページを送信した場合でも、新しいページが表示されます。 Web サーバーには、前回の要求のメモリがありません。 どちらも ASP.NET せず、ブラウザーも実行しません。 ページのこれらの個別のインスタンス間の唯一の接続は、それらの間で送信するすべてのデータです。 たとえば、ページを送信した場合、新しいページ インスタンスは、以前のインスタンスによって送信されたフォーム データを取得できます。 (ページ間でデータを渡すもう 1 つの方法は、Cookie を使用することです)。

この状況を正式に説明する方法は、Web ページが ステートレスであると言う点です。 Web サーバーとページ自体とページ内の要素は、ページの以前の状態に関する情報を保持しません。 Web はこのように設計されています。これは、個々の要求の状態を維持すると、Web サーバーのリソースがすぐに使い果たされ、多くの場合、1 秒あたり数千 (数十万) の要求を処理するためです。

そのため、テキスト ボックスは空でした。 ページを送信した後、ASP.NET ページの新しいインスタンスを作成し、コードとマークアップを実行しました。 そのコードには、テキスト ボックスに値を入力するように ASP.NET に示すものは何もありませんでした。 そのため、ASP.NET は何も行わず、テキスト ボックスに値なしでレンダリングされました。

実際には、この問題を回避する簡単な方法があります。 テキスト ボックスに入力したジャンル は、 コード内で使用できます。これは にあります Request.QueryString["searchGenre"]

次の例のように、 属性が からsearchTerm値をvalue取得するように、テキスト ボックスのマークアップを更新します。

<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />

このページでは、入力した value ジャンルもその変数に searchTerm 含まれるため、 属性を 変数に設定することもできます。 ただし、次に Request 示すように、 オブジェクトを value 使用して属性を設定することが、このタスクを実行する標準的な方法です。 (場合によっては、フィールドに値 を含めず にページをレンダリングすることもできます。これはすべて、アプリで何が起こっているかによって異なります)。

Note

パスワードに使用されるテキスト ボックスの値を "記憶" することはできません。 ユーザーがコードを使用してパスワード フィールドに入力できるようにするセキュリティ ホールになります。

ページをもう一度実行し、ジャンルを入力して、[ ジャンルの検索] をクリックします。 今回は、検索結果が表示されるだけでなく、テキスト ボックスには前回入力した内容が記憶されます。

テキスト ボックスに前のエントリが

タイトルで任意のWordを検索する

任意のジャンルを検索できるようになりましたが、タイトルを検索することもできます。 検索するときに正確にタイトルを取得するのは難しいので、代わりにタイトル内の任意の場所に表示される単語を検索できます。 SQL でこれを行うには、次のような 演算子と構文を使用 LIKE します。

SELECT * FROM Movies WHERE Title LIKE '%adventure%'

このコマンドは、タイトルに "adventure" が含まれているすべての映画を取得します。 演算子を LIKE 使用する場合は、検索用語の一部としてワイルドカード文字 % を含めます。 検索 LIKE 'adventure%' は "'adventure' から始まる" を意味します。 (技術的には、"文字列 'adventure' の後に何も続くもの" を意味します)。同様に、検索用語 LIKE '%adventure' は "文字列 'adventure' の後に続くものすべて" を意味します。これは、"'adventure' で終わる" というもう 1 つの方法です。

したがって、検索用語 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);
}

このコードの動作の概要は次のとおりです。

  • 変数 searchTermselectCommand は、上部で初期化されます。 これらの変数は、ユーザーがページで実行する内容に基づいて、適切な検索用語 (存在する場合) と適切な SQL コマンドに設定します。 既定の検索は、データベースからすべてのムービーを取得する単純なケースです。
  • searchTitleのテストsearchGenreでは、コードは検索する値に設定searchTermされます。 これらのコード ブロックは、その検索に適した SQL コマンドにも設定 selectCommand されます。
  • メソッドは db.Query 、 に含まれる SQL コマンドと 内 selectedCommand の値 searchTermを使用して、1 回だけ呼び出されます。 検索語句がない (ジャンルがなく、タイトル ワードがない) 場合、 の値は空の searchTerm 文字列です。 ただし、その場合、クエリにはパラメーターが必要ないため、それは重要ではありません。

タイトル検索機能のテスト

これで、完成した検索ページをテストできます。 Movies.cshtml を実行します

ジャンルを入力し、[ ジャンルの検索] をクリックします。 グリッドには、以前と同様に、そのジャンルのムービーが表示されます。

タイトル ワードを入力し、[ タイトルの検索] をクリックします。 グリッドには、タイトルにその単語を含むムービーが表示されます。

タイトルで 'The' を検索した後の映画ページの一覧

両方のテキスト ボックスを空白のままにして、いずれかのボタンをクリックします。 グリッドにすべてのムービーが表示されます。

クエリの組み合わせ

実行できる検索が排他的であることがわかります。 両方の検索ボックスに値が含まれている場合でも、タイトルとジャンルを同時に検索することはできません。 たとえば、タイトルに "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">
  <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>

その他のリソース