検索

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

インデックス フォームの更新

まず、アクション メソッドを既存MoviesControllerIndexクラスに更新します。 コードは次のとおりです。

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 クエリは、定義されている場合や、 や などのWhereOrderByメソッドを呼び出して変更された場合には実行されません。 代わりに、クエリの実行は遅延されます。つまり、式の評価は、その実現値が実際に反復処理されるか ToList 、メソッドが呼び出されるまで遅延されます。 Searchこのサンプルでは、Index.cshtml ビューでクエリが実行されます。 クエリの遅延実行の詳細については、「クエリの実行」を参照してください。

Note

Contains メソッドは、上記の c# コードではなく、データベースで実行されます。 データベースの ContainsSQL LIKE にマップされます。大文字と小文字は区別されません。

これで、フォームをユーザーに Index 表示するビューを更新できます。

アプリケーションを実行し、 /Movies/Index に移動します。 ?searchString=ghost などのクエリ文字列を URL に追加します。 フィルターされたムービーが表示されます。

SearchQryStr

メソッドのシグネチャを という名前ididIndexパラメーターに変更すると、パラメーターは、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 セグメント) として検索タイトルを渡すことができます。

M V C Movie Index ページを示すスクリーンショット。ローカル ホスト コロン 1 2 3 4 スラッシュムービースラッシュ インデックススラッシュ ゴーストは、U R L フィールド内にあり、赤で囲まれています。

ただし、ユーザーがムービーを検索するたびに 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は正しいコントローラー アクション メソッドを呼び出してビューを表示します。

[Index dot c s h t m l]\(インデックス ドット c s h t m l\) タブを示すスクリーンショットソリューション エクスプローラー開いています。ソリューション エクスプローラーでは、サブフォルダー Movies が開き、インデックス ドット c s h t m l が選択されています。

Visual Studio でインデックス ビューを開いた状態で (上の図に示すように)、Ctr F5 または F5 をタップしてアプリケーションを実行し、ムービーを検索してみてください。

[タイトル] フィールドにタイトルが入力された [インデックス] ページを示すスクリーンショット。

メソッドのIndexオーバーロードはありませんHttpPost。 メソッドはアプリケーションの状態を変更せず、単にデータをフィルター処理するため、必要ありません。

以下の HttpPost Index メソッドを追加できます。 その場合、アクション呼び出し元は メソッドと一致 HttpPost IndexHttpPost Index 、次の図に示すように メソッドが実行されます。

[HttpPost] 
public string Index(FormCollection fc, string searchString) 
{ 
    return "<h3> From [HttpPost]Index: " + searchString + "</h3>"; 
}

SearchPostGhost

ただし、この 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))

BeginFormPost_SM

検索を送信すると、URL に検索クエリ文字列が含まれます。 HttpPost Index メソッドがある場合でも、検索時には HttpGet Index アクション メソッドにも移動します。

IndexWithGetURL

ジャンル別検索の追加

メソッドのバージョンを追加した 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キーを提供しますViewBagIEnumerable<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 方法と、テスト データベースを自動的に作成する初期化子を追加する方法について説明します。