Part 3. ASP.NET MVC Core 1.0 の基本的な使い方
では、データアクセスができるようになったところで、ASP.NET MVC Core 1.0 の基本的な使い方を見ていくことにします。
■ ASP.NET MVC の超簡単解説
ASP.NET Web Forms しか開発したことがない方のために、超ざっくりと ASP.NET MVC を解説しておきます。(ASP.NET MVC を触ったことがある方はここは飛ばしていただいて OK です。)
- ASP.NET MVC とは、論理 3 階層型の Web アプリケーション(UI/BC/DAC に分解される Web アプリケーション)を開発する際に、UI 部分を「きれいに分解しながら」作ることができる技術のひとつ。
- クライアントのブラウザから、特定のコントローラクラスのアクションメソッドを呼び出すと、それに対応する処理が動き、対応するビューによりレスポンス HTML データが作成され、ブラウザに返却される、という仕組みになっている。
ASP.NET MVC に関して、まず特に覚えておいていただきたいポイントは以下の 3 つです。
- ブラウザからのリクエストは、URL で指定されたコントローラクラスのアクションメソッドで処理される。
- 例えば、ブラウザから https://localhost:xxx/Sample01/GetAuthors/ という URL を呼び出すと、Sample01Controller.cs というクラスの、GetAuthors() というメソッドが呼び出される。(第一引数でコントローラクラス名を指定し、第二引数でアクションメソッド名を指定する。 )
- このメソッドの中では、ビジネスロジッククラスやデータアクセスクラスを呼び出してデータベースからデータを取り出したり、処理結果をビューに引き渡したりする。
- クライアントに送り返す HTML データは、対応するビューファイル(.cshtml ファイル)により作成される。
- コントローラクラスからデータを受け取り、それを使って、クライアントに送り返す HTML ページを作成する。
- ASP.NET MVC では、モデルに相当するものが何であるのかは決まっていない。
- ここは重要なポイントですが、”MVC” = Model + View + Controller という名前がついているものの、ASP.NET MVC において明確に扱いが決まっているのは Controller と View のみであり、Model が何であるのかの定義はありません。
- 一般的には、以下のうちのいずれか(または複数)が Model に相当します。(詳細は本 blog を読み進めていくうちにわかってくると思いますので、ここではわからなくてもよいです。)
- ① データベースとやり取りされるデータの構造(=EF のデータモデル)
- ② ビューに対して引き渡すデータの構造(=ビューモデル)
- ③ クライアントから送られてくるデータの構造(=リクエストパラメータバインディングのモデル)
では前置きはこのぐらいにして、具体的な実装を見ながら説明していきます。
■ ASP.NET MVC Core ランタイムの組み込み
ASP.NET Core 1.0 のデフォルト状態では、何もアプリケーションランタイムが組み込まれていません。このため、Startup.cs の Configure() メソッドを修正し、ASP.NET MVC Core 1.0 ランタイムを組み込みます。
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
Part 1. で説明したように、project.json ファイルにてライブラリに対する参照設定を加えたのち、ConfigureServices() メソッドに services.AddMvc() メソッドを、また Configure() メソッドに app.UseMvcWithDefaultRoute() メソッドを追加します。これにより、このアプリで MVC が利用できるようになります。
なお、ConfigureServices(), Configure() メソッドは、サンプルコードによって引数が違っていたりします。これは ASP.NET ランタイムの DI コンテナ機能によるものですが、わからなければとりあえず引数が違っていてもあまり気にしなくてよい、と思っておいてください。
ではまず手始めに、データベースから著者データを取ってきて一覧表示するアプリを作ってみます。(いつもながら芸がないですがw)
■ コントローラクラスとビューファイルの配置
まずプロジェクトに Controllers という名前のフォルダを掘り、そこに HomeController.cs という名前で C# のクラスファイルをひとつ追加します。なお、以降ではフォルダ名やクラス名、ファイル名などの大文字・小文字、単数形・複数形に注意してください。ASP.NET MVC Core では、名前が正しく規約に基づいてつけられていることを元に動作します。標準的な名付けルールに則ることで、構成設定などを書く手間を減らすことができます。(この考え方を「設定より規約」と呼び、ASP.NET MVC はこの考え方に基づいて作られています。)
作成したら、以下のような HomeController クラスを実装します。ポイントは以下の通りですが、いずれも ASP.NET MVC のお約束の書き方だと思って覚えてください。
- コントローラクラスは、必ず Controller クラスを継承させて作る。
- アクションメソッドの戻り値は必ず ActionResult クラスとする。
- 実際にメソッドを終了するときは、View() を返す。 (※ このメソッドは、Controller クラスが持っているメソッドで、ActionResult クラスを継承した ViewResult クラスのインスタンスを返します。)
- このページを呼び出す HTTP プロトコルを制限したい場合には、属性 [HttpGet] や [HttpPost] などを指定します。(無指定だとどんなプロトコルでも呼び出しが可能になります。)
using Microsoft.AspNetCore.Mvc;
namespace Decode2016.WebApp.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
}
続いて、Views というフォルダ、その下に Home というフォルダを作成し、その下に Index.cshtml という名前で MVC ビューページという項目を配置します。
この中に、クライアントに送り返す HTML データを記述します。いったんファイルの中身を全部消し、以下のように記述します。
<!DOCTYPE html>
<html>
<head>
<title>著者データ一覧</title>
</head>
<body>
これからコードを書く...
</body>
</html>
ここまで作成したらアプリを実行し、https://localhost:xxxx/Home/Index/ を呼び出します。すると、① コントローラクラスのアクションメソッドが呼び出され、② そこから return View(); によりビューファイルが呼び出され、③ Views/Home/Index.cshtml ファイルから HTML データが作られ、ブラウザに送り返されます。
※ なお、この例では https://localhost:xxxx/ を呼び出しも同じ結果になります。これは、ASP.NET MVC では、パスを省略すると /Home/Index を呼び出したと解釈されるためです。(Startup.cs ファイルに記述した app.UseMvcWithDefaultRoute(); の中に、既定値の設定が含まれています)
では、基本的な構造ができたので、ここにプログラムを作りこんでいきます。
■ データアクセスページの作成
HomeController クラスの Index() メソッド内に、データを取り出すコードを記述します。ビジネスロジッククラスを別に作って呼び出しても構いませんが、今回のサンプルではここに直接データアクセスコードを記述してしまうことにします。
取り出したデータは、ViewData という汎用的な入れ物を使ってビューに引き渡すことができます。
using Microsoft.AspNetCore.Mvc;
using Decode2016.WebApp.Models;
using System.Linq;
namespace Decode2016.WebApp.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
using (PubsEntities pubs = new PubsEntities())
{
var query = from a in pubs.Authors select a;
ViewData["Authors"] = query.ToList();
}
return View();
}
}
}
続いて、Index.cshtml ファイルを書き換えます。*.cshtml ファイルでは Razor と呼ばれる構文を利用し、サーバ側でレンダリングを行います。
@using Decode2016.WebApp.Models
<!DOCTYPE html>
<html>
<head>
<title>著者データ一覧</title>
</head>
<body>
@{
var authors = (List<Author>)ViewData["Authors"];
}
<table>
<thead>
<tr>
<th>著者ID</th>
<th>著者名</th>
<th>電話番号</th>
<th>契約有無</th>
</tr>
</thead>
<tbody>
@foreach (var a in authors)
{
<tr>
<td>@a.AuthorId</td>
<td>@a.AuthorFirstName @a.AuthorLastName</td>
<td>@a.Phone</td>
<td>@(a.Contract ? "契約あり" : "契約なし")</td>
</tr>
}
</tbody>
</table>
</body>
</html>
要点を以下に解説します。
- *.cshtml ファイルは、サーバサイドで HTML データを作り出すために使われます。
- classic ASP(ASP.NET の前の技術)に非常によく似た技術です。大昔を知っている方ならむしろ馴染み深いものかもしれません。
- Razor 構文では、@ マークを使って C# のコードを記述します。
- 基本構文は @{ … } ですが、カッコなしで @foreach { … } といきなり命令を書くこともできます。
また、Razor 構文では HTML 出力を簡単に作れるようになっています。例えば…
以下のように書くべきところを… | 以下のように書ける |
@{ Write(DateTime.Now);} | @DateTime.Now |
@{ Write(“<td>” + a.AuthorId + “</td>”);} | <td>@a.AuthorId</td> |
といった感じです。慣れるとサクサクと書けます。実行してみるとこんな感じです。
このサンプルを見て、<table> タグを自力で書かなければならないのかよ! と思われた方、はい、その通りです。
- ASP.NET Web Forms の場合、GridView という便利な部品が存在していましたが、ASP.NET MVC Core では(今のところ)そのような高機能な便利部品は存在していません。ちなみに ASP.NET MVC 5 には WebGrid という部品は存在しており、これについてはいずれ ASP.NET MVC Core にも移植されると思いますが、ASP.NET Web Forms の GridView に比べるとかなり機能的には劣ります。なので、過度な期待は禁物です。
- ASP.NET Web Forms で利用していたような高機能なグリッド部品が必要な場合には、3rd party 製の部品に頼る形になります。この詳細については、この後の SPA 型アプリ開発のセクションで解説します。
■ ASP.NET MVC のフォルダ/ファイルのレイアウトルール
ここまで見てきた例からわかるように、ASP.NET MVC では、フォルダ/ファイル/メソッドのレイアウトと命名にルールがあります。上では 1 つのページしかありませんでしたが、もしこれが本格的な Web アプリになったらどうなるかを考えてみます。例えば、以下のような業務構造・画面遷移を持つアプリを作ろうと思ったとします。
この場合には、以下のようにファイルをレイアウトします。(※ コントローラクラスの中には、各ページに対応する複数のアクションメソッドが並ぶことになります。) このファイルのレイアウト関係を、しっかり頭に入れておいてください。
基本的な ASP.NET MVC のアプリの作り方がわかったら、今度はページの構造化をしていくことにします。