【T4a】モデルとビューの連携(前編)(6/7)
プロジェクトタイプ | ASP.NET Core Web アプリ(Model-View-Controller) |
---|---|
プロジェクト名 | T4a |
ソリューション名 | PIT4 |
ターゲットフレームワーク | .NET 8.0(長期的なサポート) |
最上位レベルのステートメントを使用しない | 使用する(チェックオフ) |
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備作業を参照せよ.
4a-6. エラーメッセージやテクニカルドキュメントの読解
ここまで入力したら実行してみよう. アプリケーションの実行環境として http が選択されていることと, 表示に使用するウェブブラウザが Firefox を選択されていることを確認して実行する.すると_に示すように エラーとなるはずである.
これはアクションやビューの表示に際して例外が送出されたことを意味する画面である.ここで重要なアドバイスを 書いておこう.エラーが起きたときは必ずエラーメッセージを読もう.
重要なことなのでもう一度書いて強調する.エラーが起きたときは必ずエラーメッセージを読もう. エラーが起きたときに「エラーが起こった」ということしか認識しないのでは解決の糸口をつかむことはできない. エラーメッセージはその原因を示唆するためにシステムやフレームワークが意図的に表示させているものであって, エラーそれ自体は,必ずしも致命的な失敗を意味しているわけではない. むしろ意図しない状況を検出して,そのまま処理を続けてしまうことによって致命的な結果を招かないために エラーを通知して処理を止めているともいえる.
エラーメッセージはこの演習ではほとんどが英文表記となるが,簡単な英文なのできちんと解読してみよう. 読者の中には英語を苦手とするものもいると思われるが,少し厳しい言い方をすれば 「英語が苦手」などと 言っているようではいつまで経っても一人前の技術者にはなれないし,親切な誰かが翻訳してくれることを期待して待っているだけでは 技術的に周回遅れになってしまう .技術英語はそれほど難しくないものなので臆せず読むようにするべきである. では,先ほどのエラー画面の冒頭を引用してみよう.
An unhandled exception occurred while processing the request.
ArgumentNullException: Value cannot be null. (Parameter 'Model')
AspNetCoreGeneratedDocument.Views_Home_Index.ExecuteAsync() in Index.cshtml, line 6
これをできるだけ訳してみると以下のようになる.
リクエストを処理している最中に捕捉されない例外が発生した.
ArgumentNullException: 値は null にできない(パラメータ`Model`)
AspNetCoreGeneratedDocument.Views_Home_Index.ExecuteAsync() in Index.cshtml, line 6
こういったメッセージの意図を掴むには多少慣れが必要であるが,今回のような
例外メッセージを読むときはその内容と発生場所に着目するとよいだろう.エラーの内容は2行目で示唆されているように
ArgumentNullException例外である.
これは null に対して何らかの操作を行おうとしたときに投じられるものである
(参考:プログラミング演習Ⅲ(2023; 金澤クラス)第02回).
そしてその「 null であった何か」は,Model
という名前であると報告されている((Parameter 'Model')
).
また4行目を見てみよう.記述の大半は無視してもよいが重要なのは in Index.cshtml, line 6
の部分である.
Index.cshtml というファイルの6行目からエラーが発生している,ということをこのメッセージは示唆している.
実は今回のこのエラーは意図的に起こしているものである. Index.cshtml ,すなわちリスト4a-5-3の
6行目ではモデルクラスが null ではないことをチェックして, null である場合に意図的に例外を投じるようにしている.
前述した通り,@model
ディレクティブを指定しているビューでは
Model
という変数を通じて,関連付けられているモデルクラスのインスタンスを操作することができるが,
コントローラーのアクション(≒メソッド)側の処理でモデルクラスのインスタンスを明示的に指定しない限りModel
は null となる.
ASP.NET Core MVC のプロジェクトを作成すると,プロジェクト内にHome
というコントローラーがあらかじめ作られている.
今回のこの Index.cshtml というビューに対応するのは,このコントローラーのメソッドなのでそのソースコードを覗いてみよう.
Controllers フォルダ内に HomeController.cs というファイルがあるので
これを開いてみよう.デフォルトでは_のようになっているはずである.
|
|
強調したIndex()
メソッドが問題の「アクション側の処理」である.
ASP.NET Core ではhttp://localhost:
にアクセスすると,
まずポート番号
/コントローラー名
/アクション名
コントローラー名
で指定されるコントローラークラスのアクション名
のメソッドが呼び出される.このときにクライアントに
返送されるページ(=HTML)を生成するのにViews/
が使われるが,
これはアクションメソッドの return 文でView()メソッドを呼び出しているためである.
コントローラー名
/アクション名
.cshtmlView()
メソッドは_の18行目,23行目などでそうしているように引数なしで呼び出すこともできるが,
この場合は対応するビューにモデルクラスが関連付けられていた場合はModel
変数が null となる.
ここでプログラミング技術に関連するドキュメントの読み方についても少し説明しておこう.C#をはじめ ASP.NET Core も Microsoft 社が
提供しているものであり,そのすべての公式情報はマイクロソフトのドキュメントに掲載されている
1.
ではView()
メソッドの公式のドキュメントを読んでみよう.
前述の「View()メソッド」のリンクをたどってみよう.
_のようにView()
メソッドにはいくつかのオーバーロード(=引数の組み合わせ違いの同名のメソッド)が存在することが分かる.
引数なしのView()
メソッドの作用は先ほど説明した通りであるが,View()
メソッドには
object型の引数を一つ受け取るオーバーロードが存在している.このオーバーロードに対しては_の
ような説明が掲載されているはずである.
現状Microsoftのドキュメントは日本語訳もいちおう提供されているが,この日本語訳はほとんどが機械翻訳によるものでありその品質は たいへん低いため英語のまま読むことを強く推奨する.情報技術者としてプログラミング技術にかかわる限り英語ドキュメントを読むことは不可避であるため, 英語のドキュメントはそのまま読めるようにしておこう.慣れないうちは機械翻訳に頼るのもよいが,機械翻訳では必ずしも原文の意味や意図を正確に翻訳してくれるとは限らないので注意が必要である. 機械翻訳による微妙なニュアンスの変質や解釈の誤りが致命的な不具合を生み出してしまう場合もあるため,できるだけ原文をそのまま読むようにしよう.
では前述の object 型の引数を一つ受け取るView()
メソッドのオーバーロードの説明を見てみよう.該当部分をそのまま引用する.
View(Object)
Creates a ViewResult object by specifying a
model
to be rendered by the view.[Microsoft.AspNetCore.Mvc.NonAction] public virtual Microsoft.AspNetCore.Mvc.ViewResult View (object? model);Parameters
model
- Object
The model that is rendered by the view.
Returns
The created ViewResult object for the response.
Attributes
- NonActionAttribute
このドキュメントではこのメソッドの作用や各々の引数の意味,戻り値といったことを説明している.識別子以外の部分を可能な限り訳すと以下のようになるだろう. 特に強調部分に着目する.
View(Object)
ビューで表示される
model
を指定して,ViewResultを作成する.[Microsoft.AspNetCore.Mvc.NonAction] public virtual Microsoft.AspNetCore.Mvc.ViewResult View (object? model);戻り値
レスポンスのために作成されたViewResultオブジェクト
Attributes
- NonActionAttribute
説明の通り,この引数付きのView()
メソッドに何かしらの引数を渡すとそれがビューに関連付けられたモデルとして扱われる.
_で強調したデフォルトのままのIndex
アクションでは,View()
メソッドを引数なしで呼び出しているため,
ビューで@model
ディレクティブが使用されていたとしてもModel
変数は null のままとなる.つまり,ビュー側でモデルクラスのインスタンスが
渡されていることを前提とするならば,代わりにこの引数付きのView()
メソッドを使用しなければならない,ということである.
したがってHome
コントローラのIndex
アクションを_に示すように修正する.
|
|
ここまで書けたら実行してみよう.図4a-7-2のように入力欄に「0」があらかじめ入力された状態で表示されるはずである.
では_に示すように,これらの入力を削除して空欄にしたうえで「送信」ボタンをクリックしてみよう.
すると_のようにエラーメッセージが表示されるはずである. ここですでにクラスの定義から入力内容の制約に関する推定が働いている .
リスト4a-5-1のHealthInfo
クラスの定義を見ると,Weight
およびHeight
プロパティの型はともに double 型である.
ASP.NET Core では, null を代入できない型(=Null非許容な型)のプロパティは基本的に入力必須の項目である とみなされる.
逆に int? 型や string? 型などのように null を代入できる型のプロパティはオプショナル(=任意入力)な項目となる
(Null 許容型の概念については本コースの第02回も参照せよ).
古くからの技術者はよくこのサイトを「MSDNのドキュメント」などと呼ぶことがある ↩︎