検索
Note
このチュートリアルの更新バージョンは、Visual Studio の最新バージョンを使用してこちらで入手できます。 新しいチュートリアルでは、MVC ASP.NET Core使用します。このチュートリアルでは、このチュートリアルに対して多くの機能強化が提供されます。
このチュートリアルでは、ASP.NET Core MVC のコントローラーとビューについて説明します。 Razor Pages は、ASP.NET Coreの新しい代替手段であり、Web UI の構築を容易かつ生産的にするページ ベースのプログラミング モデルです。 MVC バージョンの前に Razor Pages チュートリアルを試してみることをお勧めします。 この Razor ページのチュートリアルの特徴は次のとおりです。
- 使いやすい。
- 多くの機能をカバーしている。
- 新しいアプリ開発に推奨されるアプローチです。
検索メソッドと検索ビューの追加
このセクションでは、ジャンルまたは名前で映画を Index
検索できるアクション メソッドに検索機能を追加します。
前提条件
このセクションのスクリーンショットと一致するには、アプリケーション (F5) を実行し、次のムービーをデータベースに追加する必要があります。
タイトル | リリース日 | Genre | Price |
---|---|---|---|
ゴーストバスターズ | 6/8/1984 | コメディ | 6.99 |
ゴーストバスターズ II | 6/16/1989 | コメディ | 6.99 |
猿の惑星 | 3/27/1986 | アクション | 5.99 |
インデックス フォームの更新
まず、アクション メソッドを既存MoviesController
のIndex
クラスに更新します。 コードは次のとおりです。
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
メソッドの最初の行では Index
、次の LINQ クエリを作成してムービーを選択します。
var movies = from m in db.Movies
select m;
クエリはこの時点で定義されていますが、データベースに対してまだ実行されていません。
パラメーターに文字列が searchString
含まれている場合は、次のコードを使用して、検索文字列の値をフィルター処理するように movies クエリが変更されます。
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
上の s => s.Title
コードはラムダ式です。 ラムダは、上記のコードで使用されている Where メソッドなどの標準クエリ演算子メソッドの引数として、メソッドベースの LINQ クエリで使用されます。 LINQ クエリは、定義されている場合や、 や などのWhere
OrderBy
メソッドを呼び出して変更された場合には実行されません。 代わりに、クエリの実行は遅延されます。つまり、式の評価は、その実現値が実際に反復処理されるか ToList
、メソッドが呼び出されるまで遅延されます。 Search
このサンプルでは、Index.cshtml ビューでクエリが実行されます。 クエリの遅延実行の詳細については、「クエリの実行」を参照してください。
Note
Contains メソッドは、上記の c# コードではなく、データベースで実行されます。 データベースの Contains は SQL LIKE にマップされます。大文字と小文字は区別されません。
これで、フォームをユーザーに Index
表示するビューを更新できます。
アプリケーションを実行し、 /Movies/Index に移動します。 ?searchString=ghost
などのクエリ文字列を URL に追加します。 フィルターされたムービーが表示されます。
メソッドのシグネチャを という名前id
id
のIndex
パラメーターに変更すると、パラメーターは、App_Start\RouteConfig.cs ファイルで設定された既定のルートのプレースホルダーと一致{id}
します。
{controller}/{action}/{id}
元 Index
のメソッドは次のようになります。
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
変更された Index
メソッドは次のようになります。
public ActionResult Index(string id)
{
string searchString = id;
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
これで、クエリ文字列の値ではなく、ルート データ (URL セグメント) として検索タイトルを渡すことができます。
ただし、ユーザーがムービーを検索するたびに URL の変更を求めることはできません。 そのため、ここでは UI を追加して、ムービーをフィルターできるようにします。 ルート バインド ID パラメーターを渡す方法をテストするために メソッドのIndex
シグネチャを変更した場合は、メソッドが という名前searchString
の文字列パラメーターをIndex
受け取るように、それを元に戻します。
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
Views\Movies\Index.cshtml ファイルを開き、 の直後@Html.ActionLink("Create New", "Create")
に、次に強調表示されているフォーム マークアップを追加します。
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
</p>
ヘルパーは Html.BeginForm
開始 <form>
タグを作成します。 ユーザーが Html.BeginForm
[ フィルター ] ボタンをクリックしてフォームを送信すると、ヘルパーによってフォームがそれ自体に投稿されます。
Visual Studio 2013は、ファイルの表示と編集を行うときに優れた改善を行いました。 ビュー ファイルを開いた状態でアプリケーションを実行すると、Visual Studio 2013は正しいコントローラー アクション メソッドを呼び出してビューを表示します。
Visual Studio でインデックス ビューを開いた状態で (上の図に示すように)、Ctr F5 または F5 をタップしてアプリケーションを実行し、ムービーを検索してみてください。
メソッドのIndex
オーバーロードはありませんHttpPost
。 メソッドはアプリケーションの状態を変更せず、単にデータをフィルター処理するため、必要ありません。
以下の HttpPost Index
メソッドを追加できます。 その場合、アクション呼び出し元は メソッドと一致 HttpPost Index
し HttpPost Index
、次の図に示すように メソッドが実行されます。
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
ただし、この HttpPost
バージョンの Index
メソッドを追加しても、実装方法は制限されます。 たとえば、特定の検索をブックマークするか、友だちにリンクを送信し、友だちがそれをクリックしてムービーのフィルターされた同じリストを表示できるようにするとします。 HTTP POST 要求の URL が GET 要求の URL (localhost:xxxxx/Movies/Index) と同じであることに注意してください。URL 自体に検索情報はありません。 現在、検索文字列情報はフォーム フィールド値としてサーバーに送信されます。 つまり、その検索情報をキャプチャしてブックマークしたり、URL で友人に送信したりすることはできません。
解決策は、 のオーバーロードを使用することです。このオーバーロードBeginForm
では、POST 要求で検索情報を URL に追加し、メソッドのIndex
バージョンにルーティングするHttpGet
必要があることを指定します。 既存のパラメーターなしの BeginForm
メソッドを次のマークアップに置き換えます。
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
検索を送信すると、URL に検索クエリ文字列が含まれます。 HttpPost Index
メソッドがある場合でも、検索時には HttpGet Index
アクション メソッドにも移動します。
ジャンル別検索の追加
メソッドのバージョンを追加した HttpPost
場合は Index
、ここで削除します。
次に、ユーザーがジャンル別に映画を検索できるようにする機能を追加します。 Index
メソッドを次のコードに置き換えます。
public ActionResult Index(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
return View(movies);
}
このバージョンの メソッドは Index
、 という movieGenre
追加のパラメーターを受け取ります。 最初の数行のコードでは、 List
データベースから映画のジャンルを保持するオブジェクトが作成されます。
次のコードは、データベースからすべてのジャンルを取得する LINQ クエリです。
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
このコードでは、 AddRange
ジェネリック List
コレクションの メソッドを使用して、すべての異なるジャンルをリストに追加します。 (修飾子がないと Distinct
、重複するジャンルが追加されます。たとえば、このサンプルではコメディが 2 回追加されます)。 その後、コードはオブジェクトにジャンルの一覧を ViewBag.MovieGenre
格納します。 カテゴリ データ (映画のジャンルなど) を SelectList オブジェクトとして に ViewBag
格納し、ドロップダウン リスト ボックスでカテゴリ データにアクセスすることは、MVC アプリケーションの一般的なアプローチです。
次のコードは、 パラメーターをチェックする方法をmovieGenre
示しています。 空でない場合、コードは movies クエリをさらに制限して、選択したムービーを指定したジャンルに制限します。
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
前に説明したように、ムービー リストが反復処理されるまで (アクション メソッドが返された後 Index
に View で実行される) まで、クエリはデータベースで実行されません。
ジャンル別検索をサポートするためのインデックス ビューへのマークアップの追加
ヘルパーの Html.DropDownList
直前にある Views\Movies\Index.cshtml ファイルにヘルパーを TextBox
追加します。 完成したマークアップを次に示します。
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("Index", "Movies", FormMethod.Get))
{
<p>
Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" />
</p>
}
</p>
<table class="table">
次のコードの内容は以下のとおりです。
@Html.DropDownList("movieGenre", "All")
パラメーター "MovieGenre" は、 内で を見つけるためのヘルパーのDropDownList
キーを提供しますViewBag
。IEnumerable<SelectListItem>
ViewBag
アクション メソッドに が設定されました。
public ActionResult Index(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
return View(movies);
}
パラメーター "All" はオプション ラベルを提供します。 ブラウザーでその選択を検査すると、その "value" 属性が空であることがわかります。 コントローラーは文字列をフィルター処理 if
するだけで済むので、 null
の空の値 movieGenre
を送信するとすべてのジャンルが表示されます。
既定で選択するオプションを設定することもできます。 既定のオプションとして "Comedy" が必要な場合は、コントローラーのコードを次のように変更します。
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
アプリケーションを実行し、 /Movies/Index を参照します。 ジャンル、映画名、両方の条件で検索してみてください。
このセクションでは、検索アクション メソッドを作成し、ユーザーが映画のタイトルとジャンルで検索できるようにするビューを作成しました。 次のセクションでは、モデルにプロパティを追加する Movie
方法と、テスト データベースを自動的に作成する初期化子を追加する方法について説明します。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示