Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8899

ASP.NET Core 3.0 Razor Pages 事始め(8) - 検索機能の追加

$
0
0

ASP.NET Core 3.0 Razor Pages 事始め(7)の続きです。

今回は公式チュートリアルのASP.NET Core Razor ページへの検索の追加に沿って進めていこうと思います。

IndexModel へプロパティを追加

Indexページで検索機能を追加します。

まずは、IndexModelに、検索用のプロパティを追加します。

usingMicrosoft.AspNetCore.Mvc.Rendering;publicclassIndexModel:PageModel{privatereadonlyRazorPagesMovie.Models.RazorPagesMovieContext_context;publicIndexModel(RazorPagesMovie.Models.RazorPagesMovieContextcontext){_context=context;}publicIList<Movie>Movies{get;set;}[BindProperty(SupportsGet=true)]publicstringSearchString{get;set;}// Requires using Microsoft.AspNetCore.Mvc.Rendering;publicSelectListGenres{get;set;}[BindProperty(SupportsGet=true)]publicstringMovieGenre{get;set;}publicasyncTaskOnGetAsync(){Movies=await_context.Movies.ToListAsync();}}

追加したのは、以下の3つのプロパティです。

SearchString

ユーザーが検索テキスト ボックスに入力した値がここに入ります。
[BindProperty] 属性で修飾されています。これで、HTMLの同じ名前のフォーム要素(あるいはクエリ文字列)がこのプロパティにバインドされます。 SupportsGet = trueは、GET 要求でのバインドで必要です。

Genres

ジャンル一覧を表しています。 選択一覧に表示される項目として利用されます。SelectListクラスは Microsoft.AspNetCore.Mvc.Rendering名前空間に定義されています。

MovieGenre

ユーザーが選択したジャンルが入ります。SearchStringプロパティと同様に、[BindProperty] 属性で修飾されています。

IndexModel の OnGetAsync メソッド変更

次に、IndexModel の OnGetAsync メソッドを変更します。変更後のOnGetAsyncメソッドを示します。

publicasyncTaskOnGetAsync(){varmovies=_context.MoviesasIQueryable<Movie>;if(!string.IsNullOrEmpty(SearchString)){movies=movies.Where(s=>s.Title.Contains(SearchString));}Movies=awaitmovies.ToListAsync();}

このOnGetAsyncメソッドが正しく動作するかを確認してみます。
F5キーでデバッグを開始します。

ブラウザが起動したら、Moviesページに移動します。

そして、?searchString=Ghostのクエリ文字列を URLに追加して実行してみます。

https://localhost:5001/movies?searchString=Ghost

たしかに、Ghostで絞り込めました。

スクリーンショット 2019-11-12 21.32.12.png

次に、デバッグを終了し、index.chtmlを開きます。
先頭の行を以下のように書き換えます。

@page "{searchString?}"

これで、クエリ文字列の代わりに、URLのルートデータとして題名を指定できるようになります。これをルート制約と言うようです。

これも試してみます。

https://localhost:5001/movies/Ghost

先ほどと同じ結果になりました。

検索用UIの追加

しかし、URLをユーザに入力してもらうわけにはいきません。
そのため、index.cshtmlに検索のためのUIを追加します。

先ほどのルート制約を削除します。

それから、index.cshtmlを開き、以下のようの <form>要素を <table>要素の直前に追加します。

<p><aasp-page="Create">新規追加</a></p><form><p>
        @Html.DisplayNameFor(model => model.Movies[0].Title):
        <inputtype="text"asp-for="SearchString"/><buttontype="submit">検索</button></p></form><tableclass="table"><thead>

<form>のデフォルトの methodの値は、"get"なので、検索ボタンを押せば、OnGetAsyncメソッドが呼びだされます。

チュートリアルのページでは、"Title"と文字列リテラルを使っていましたが、ここでは、@Html.DisplayNameForを使うようにしてみました。

HTML的には、<label>を使ったほうが良いのかもしれませんね。でもその場合は、SearchStringプロパティに、[Display(Name ="タイトル")]という属性を付加する必要がありますね。

では、テストしてみます。
うまく動いているようです。

スクリーンショット 2019-11-12 21.36.24.png

検索フィールドを空にして、[検索]ボタンを押せば、すべてのタイトルが表示されます。

ジャンルで検索

次にジャンルで検索する機能を追加します。

index.cshtml.csの OnGetAsyncメソッドを次のように更新します。
なお、チュートリアルページのコードが僕の好みじゃないので書き換えています。

publicasyncTaskOnGetAsync(){// Moviesをフィルタリングvarmovies=_context.MoviesasIQueryable<Movie>;if(!string.IsNullOrEmpty(SearchString)){movies=movies.Where(s=>s.Title.Contains(SearchString));}if(!string.IsNullOrEmpty(MovieGenre)){movies=movies.Where(x=>x.Genre==MovieGenre);}Movies=awaitmovies.ToListAsync();// ジャンル一覧を生成vargenreList=await_context.Movies.OrderBy(m=>m.Genre).Select(m=>m.Genre).Distinct().ToListAsync();Genres=newSelectList(genreList);}

このほうが分かりやすいと個人的には思います。

次に、Index.cshtmlの<form>要素を以下のように変更します。

<form><p><selectasp-for="MovieGenre"asp-items="Model.Genres"><optionvalue="">All</option></select>
        @Html.DisplayNameFor(model => model.Movies[0].Title):
        <inputtype="text"asp-for="SearchString"/><buttontype="submit">検索</button></p></form>

へー、こんな風に、<select>要素内の<option>の一部を htmlに書くこともできるんですね。
この場合は、asp-itemsでバインドされた<option>は、

<option value="">All</option>

の下に展開されるようです。以下展開された select要素です。

<selectid="MovieGenre"name="MovieGenre"><optionvalue="">All</option><option>Comedy</option><option>Romantic Comedy</option><option>Western</option></select>

ちなみに、Allを選んだときは、Allではなく、空文字列がサーバーに送られるように、value=""としています。

ビルドが通ったら、ジャンルまたはムービーのタイトル、あるいはその両方で検索して、正しく動作するかをテストします。

正しく動作しているようです。

スクリーンショット 2019-11-12 21.42.26.png

スクリーンショット 2019-11-12 21.43.08.png


Viewing all articles
Browse latest Browse all 8899

Trending Articles