MVC アプリケーションへのビューの追加
作成者: Rick Anderson
Note
Visual Studio の最新バージョンを使用しているこのチュートリアルの更新版は、こちらからアクセスできます。 新しいチュートリアルでは ASP.NET Core MVC を使用しており、このチュートリアルよりも多くの改良が加えられています。
このチュートリアルでは、ASP.NET Core MVC のコントローラーとビューについて説明します。 Razor Pages は ASP.NET Core の新しい代替手段であり、Web UI の構築を容易にし、生産性を高めるページベースのプログラミング モデルです。 MVC のバージョンの前に、Razor ページのチュートリアルを試すことをお勧めします。 この Razor ページのチュートリアルの特徴は次のとおりです。
- 使いやすい。
- 多くの機能をカバーしている。
- 新しいアプリ開発に最適なアプローチである。
このセクションでは、クライアントへの HTML 応答の生成プロセスを簡潔にカプセル化するために、ビュー テンプレート ファイルを使用するように HelloWorldController
クラスを変更します。
Razor ビュー エンジンを使用してビュー テンプレート ファイルを作成します。 Razor ベースのビュー テンプレートには、.cshtml ファイル拡張子が付いています。このテンプレートは、C# を使用した HTML 出力の作成にエレガントな方法を提供します。 Razor では、ビュー テンプレートの作成時に必要な文字数とキーストロークの数が最小限に抑えられます。これにより、高速で流動的なコーディング ワークフローが可能になります。
現在、Index
メソッドは、コントローラー クラスでハード コーディングされるメッセージを含む文字列を返します。 次のコードに示すように、Index
メソッドを変更してコントローラーの View メソッドを呼び出します。
public ActionResult Index()
{
return View();
}
上記の Index
メソッドは、ブラウザーへの HTML 応答を生成するためにビュー テンプレートを使用しています。 上記の Index
メソッドのようなコントローラー メソッド (アクション メソッドとも呼ばれます) は、通常、string などのプリミティブ型ではなく、ActionResult (または ActionResult から派生したクラス) を返します。
Views\HelloWorld フォルダーを右クリックして、[追加] をクリックし、[MVC 5 ビューのレイアウト付ページ (Razor)] をクリックします。
[アイテムの名前の指定] ダイアログ ボックスで、「インデックス」と入力し、[OK] をクリックします。
[レイアウト ページの選択] ダイアログで、既定の _Layout.cshtml をそのまま使用し、[OK] をクリックします。
上のダイアログでは、左側のウィンドウで Views\Shared フォルダーが選択されています。 別のフォルダーにカスタム レイアウト ファイルがある場合は、それを選択できます。 レイアウト ファイルについては、チュートリアルの後半で説明します
MvcMovie\Views\HelloWorld\Index.cshtml ファイルが作成されます。
次の強調表示されたマークアップを追加します。
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>
Index.cshtml ファイルを右クリックし、[ブラウザーで表示] を選択します。
Index.cshtml ファイルを右クリックし、[Page Inspector で表示] を選択することもできます。詳細については、Page Inspector のチュートリアルをご覧ください。
または、アプリケーションを実行して、HelloWorld
コントローラー (http://localhost:xxxx/HelloWorld
) を参照します。 コントローラーの Index
メソッドは十分に機能しませんでした。このメソッドは、ブラウザーへの応答のレンダリングにビュー テンプレート ファイルを使用するように指定したステートメント return View()
実行しただけです。 使用するビュー テンプレート ファイルの名前を明示的に指定していなかったため、ASP.NET MVC は \Views\HelloWorld フォルダー内の Index.cshtml ファイルを既定で使用していました。 次の画像は、ビューにハードコーディングされた "Hello from our View Template!" という文字列が示されています。
見栄えは良いですね。 ただし、ブラウザーのタイトル バーに表示された "Index - My ASP.NET Application" と、ページの上部に示されている "Application name" という大きなリンクに注目してください。ブラウザー ウィンドウのサイズによっては、[Home]、[About]、[Contact]、[Register]、[Log in] の各リンクを表示するのに、右上の 3 つのバーをクリックする必要がある場合があります。
ビューとレイアウト ページの変更
まず、ページの上部にある "Application name" リンクを変更します。 そのテキストは、すべてのページに共通のものです。 これは、アプリケーション内のすべてのページに表示されていても、実際には 1 つの場所でのみ実装されています。 [ソリューション エクスプローラー] で /Views/Shared フォルダーに移動して、_Layout.cshtml ファイルを開きます。 このファイルは "レイアウト ページ" と呼ばれるもので、その他のすべてのページで使用される共有フォルダーにあります。
[レイアウト] テンプレートでは、1 か所でサイトの HTML コンテナー レイアウトを指定し、それをサイト内の複数のページに適用できます。 @RenderBody()
という行を見つけます。 RenderBody
は、作成したビュー固有のページがすべて表示されるプレースホルダーで、レイアウト ページに "ラップ" されています。 たとえば、[About] リンクを選択すると、RenderBody
メソッド内で Views\Home\About.cshtml ビューがレンダリングされます。
タイトル要素の内容を変更します。 レイアウト テンプレートの ActionLink を "Application name" から "MVC Movie" に、コントローラーを Home
から Movies
に変更します。 完全なレイアウト ファイルを次に示します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Movie App</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("MVC Movie", "Index", "Movies", null, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
アプリケーションを実行して、"MVC Movie " と表示されるようになったことに注目してください。 [About] リンクをクリックして、そのページにも "MVC Movie" が表示されることを確認します。 レイアウト テンプレートで 1 回の変更を加えることで、サイトのすべてのページに新しいタイトルを反映できました。
Views\HelloWorld\Index.cshtml ファイルを初めて作成したとき、次のコードが含まれていました。
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
上記の Razor コードは、レイアウト ページを明示的に設定しています。 Views\_ViewStart.cshtml ファイルを調べます。このファイルには、まったく同じ Razor マークアップが含まれています。 Views\_ViewStart.cshtml ファイルにより、すべてのビューが使用する共通レイアウトを定義するため、Views\HelloWorld\Index.cshtml ファイルからそのコードをコメント アウトまたは削除できます。
@*@{
Layout = "~/Views/Shared/_Layout.cshtml";
}*@
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>
Layout
プロパティを使用すれば、別のレイアウト ビューを設定することができます。また、null
に設定して、レイアウト ファイルが使用されないようにすることができます。
次に、Index ビューのタイトルを変更しましょう。
MvcMovie\Views\HelloWorld\Index.cshtml を開きます。 変更する場所は 2 つあります。まず、ブラウザーのタイトルに表示されるテキストを変更して、2 番目の見出し (<h2>
要素) のテキストを変更します。 これを少し変えれば、コードのどの部分でアプリのどの部分が変更されるかを確認することができます。
@{
ViewBag.Title = "Movie List";
}
<h2>My Movie List</h2>
<p>Hello from our View Template!</p>
表示される HTML タイトルを示すために、上記のコードでは ViewBag
オブジェクトの Title
プロパティを設定しています (Index.cshtml ビュー テンプレート内)。 レイアウト テンプレート (Views\Shared\_Layout.cshtml) は、前に変更した HTML の <head>
セクションの一部として <title>
要素でこの値を使用していることに注目してください。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Movie App</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
この ViewBag
アプローチを使用すると、ビュー テンプレートとレイアウト ファイルの間で簡単に別のパラメーターを渡すことができます。
アプリケーションを実行します。 ブラウザーのタイトル、プライマリ見出し、およびセカンダリ見出しが変更されていることに注意してください (ブラウザーに変更内容が表示されない場合は、キャッシュされたコンテンツを表示している可能性があります。ブラウザーで Ctrl + F5 キーを押して、サーバーからの応答が強制的に読み込まれるようにしてください)。ブラウザーのタイトルは、Index.cshtml ビュー テンプレートで設定した ViewBag.Title
と、レイアウト ファイルで追加した "- Movie App" で作成されます。
Index.cshtml ビュー テンプレートのコンテンツがどのように _Layout.cshtml ビュー テンプレートにマージされ、単一の HTML 応答がブラウザーに送信されたかにも注目してください。 レイアウト テンプレートを使用すれば、アプリケーションのすべてのページに適用される変更をとても簡単に行うことができます。
ただし、わずかな "データ" (この例では、"Hello from our View Template!" メッセージ) がハード コーディングされています。 MVC アプリケーションには "V" (ビュー) があり、"C" (コントローラー) もありますが、"M" (モデル) はまだありません。 この後で、データベースを作成し、そこからモデル データを取得する方法について説明します。
コントローラーからビューへのデータの受け渡し
ただし、データベースに移動してモデルについて説明する前に、まず、コントローラーからビューに情報を渡すことについて説明しましょう。 コントローラー クラスは、受信 URL 要求への応答で呼び出されます。 コントローラー クラスは、受信ブラウザー要求を処理し、データベースからデータを取得し、最終的にブラウザーに返す応答の種類を決定するコードを記述する場所です。 そうすることで、ビュー テンプレートはブラウザーへの HTML 応答を生成して書式を設定するために、コントローラーから使用できるようになります。
コントローラーには、ビュー テンプレートがブラウザーへの応答をレンダリングするために必要なデータやオブジェクトを提供する役割があります。 ベスト プラクティス: ビュー テンプレートでは、ビジネス ロジックの実行や、データベースとの直接的な対話操作をしないでください。 ビュー テンプレートでは、コントローラーによって提供されるデータのみを処理するようにします。 この "懸念事項の分離" を維持すれば、コードをクリーンでテスト可能な保守しやすい状態に保つことができます。
現時点では、HelloWorldController
クラスの Welcome
アクション メソッドは name
と numTimes
パラメーターを受け取ってから、ブラウザーに直接値を出力します。 この応答を文字列としてコントローラーにレンダリングさせるのではなく、ビュー テンプレートを使用するようにコントローラーを変更してみましょう。 このビュー テンプレートでは動的応答が生成されます。これは、応答を生成するために、コントローラーからビューに適量のデータを渡す必要があることを意味します。 そのために、コントローラーでビュー テンプレートが必要とする動的データ (パラメーター) を ViewBag
オブジェクトに設定して、ビュー テンプレートがアクセスできるようにします。
HelloWorldController.cs ファイルに戻って、Welcome
メソッドを変更して Message
と NumTimes
の値を ViewBag
オブジェクトに追加します。 ViewBag
は動的オブジェクトです。つまり、必要なものは何でも設定できるということです。ViewBag
オブジェクトは、その内部に何かを設定するまでプロパティは定義されません。 ASP.NET MVC のモデル バインド システムは、名前付きパラメーター (name
と numTimes
) を、アドレス バーのクエリ文字列からメソッドのパラメーターに自動的にマップします。 完全な HelloWorldController.cs ファイルは次のようになります。
using System.Web;
using System.Web.Mvc;
namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Welcome(string name, int numTimes = 1)
{
ViewBag.Message = "Hello " + name;
ViewBag.NumTimes = numTimes;
return View();
}
}
}
この時点で、ViewBag
オブジェクトには、ビューに渡すデータが自動的に格納されます。 次に、Welcome ビュー テンプレートが必要です! [ビルド] メニューの [ソリューションのビルド] (または Ctrl + Shift + B) を選択して、プロジェクトがコンパイルされていることを確認します。 Views\HelloWorld フォルダーを右クリックして、[追加] をクリックし、[MVC 5 ビューのレイアウト付ページ (Razor)] をクリックします。
[アイテムの名前の指定] ダイアログ ボックスで、「ようこそ」と入力し、[OK] をクリックします。
[レイアウト ページの選択] ダイアログで、既定の _Layout.cshtml をそのまま使用し、[OK] をクリックします。
MvcMovie\Views\HelloWorld\Welcome.cshtml ファイルが作成されます。
Welcome.cshtml ファイル内のマークアップを置き換えます。 ユーザーが指示した回数だけ "Hello" と表示するループを作成します。 次に、完全な Welcome.cshtml ファイルを示します。
@{
ViewBag.Title = "Welcome";
}
<h2>Welcome</h2>
<ul>
@for (int i = 0; i < ViewBag.NumTimes; i++)
{
<li>@ViewBag.Message</li>
}
</ul>
アプリケーションを実行して、次の URL を参照します:
http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4
URL からデータが取得され、モデル バインダーを使用してコントローラーに渡されます。 コントローラーはデータを ViewBag
オブジェクトにパッケージ化し、そのオブジェクトをビューに渡します。 その後で、ビューは HTML としてユーザーにデータを表示します。
上記のサンプルでは、コントローラーからビューにデータを渡すために ViewBag
オブジェクトを使用しました。 チュートリアルの後半で、ビュー モデルを使用して、コントローラーからビューにデータを渡します。 データを渡すためのビュー モデルのアプローチは、ビュー バッグのアプローチよりも一般的に推奨されます。 詳細については、ブログ エントリ「Dynamic V 厳密に型指定されたビュー」を参照してください。
"M" (モデル) については学習しましたが、データベースについてはまだです。 学習したことを確認し、ムービーのデータベースを作成してみましょう。