[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>ASP.NET MVC]]

* 目次 [#n8bb5f94]
#contents

*概要 [#qe050a8a]
「[[ASP.NET MVCの利用方法]]」は~
「[[ASP.NET MVCの用語]]」と比べて、~
少々高度な応用的トピックをまとめています。

*モジュール化の考え方 [#qfa205f4]

**ModelとViewの関係 [#u005fdca]
Model (0..1) <---> (1) View
**M・V・Cの役割の整理 [#p3416ea2]
まず、Model と View と Controller の役割について整理する。

**ControllerとViewの関係 [#xc23cbb6]
View (1..*) <---> (1) Controller
-Model:
--アプリケーションの基礎となるデータ構造(ViewModel)、
--およびそのデータを取得・加工する業務ロジック

***View (1) <---> (1) Controller [#va1ffd01]
ASP.NETのWebFormに近い
-View:~
Model が保持するデータ(ViewModel)を参照し、ユーザーに表示する。

***View (1..*) <---> (1) Controller [#n9abe57a]
[[スキャフォールディング(scaffolding)>ASP.NET MVCの用語#e701b267]]では、この考え方を採用している。
-Controller:
--ユーザーからの入力を受け取り、
--Model に対してデータの取得・加工を指示する。
--その結果を受けて、View に表示を指示する。

-スキャフォールディングの時のMとCの関係はCRUDと割り切っているから、~
Model (0..1) <---> (1) View (1..*) <---> (1) Controller となる。
**画面 or データモデル、どちらをベースにするか? [#ga2ea366]
ASP.NET MVCの開発は、ViewModelのModelMetadata駆動になる。

-しかし、1画面に、全てのCRUD機能が詰まっていたら、~
Model (0..1) <---> (1) View (1) <---> (1) Controller と[[WebForm>#va1ffd01]]的になる。
このため、ViewModelの設計が重要になるが、これを
-画面をベースにするか?
-データモデルをベースにするか?

***上記に中立 [#p6842b7c]
1業務、1Controllerなどの考え方でもイイ。
どちらをベースにするか?でモジュール化が異なってくる。

-前者は、更に以下の2つに分類することができる。
--画面単位のControllerを作成する場合、~
これを「[[全体View ごとに Controller を作成する方式>#va1ffd01]]」と言う。
--機能単位のControllerを作成する場合、~
これを「[[全体View をまとめる 機能単位の Controller を作成する方式>#n9abe57a]]」と言う。

-後者では、データ単位のControllerが作成される。~
これを「[[スキャフォールディング方式>#n9abe57a]]」と言う。~
「[[スキャフォールディング方式>#n9abe57a]]」は肥大しやすい傾向がある。

**Modelと全体Viewの関係 [#u005fdca]
Model (0..1) <---> (1) 全体View

***Model (0) <---> (1) 全体View [#aca38037]
全体View が、Model が保持するデータを何も表示しない状態。(静的なページなど?)

***Model (1) <---> (1) 全体View [#d22aa019]
全体View が、Model が保持するデータを参照し、ユーザーに表示している状態。~
ただし、全体View が参照できるのは「Model のプロパティ」のみであり、~
全体View から直接 Model のメソッドが呼ぶことはしない。

**Controllerと全体Viewの関係 [#xc23cbb6]
全体View (1..*) <---> (1) Controller

***全体View (1) <---> (1) Controller [#va1ffd01]
1 つの 全体View に対して、1 つの Controller を対応させる考え方。

=「全体View ごとに Controller を作成する方式」

その 全体View からは、対応する Controller へのみリクエストを送る。~
Controller の処理の結果は、対応する 全体View にのみ指示を送る、というもの。~
Controller の処理の結果を、別の 全体View に表示させたい場合は、~
Controller.RedirectToAction メソッドなどを使用して、~
その 全体View に対応した Controller に処理をリダイレクトする。

乱暴な言い方をすれば、従来の ASP.NET の WebForm に近い考え方、と言えるかもしれない。
-画面 (*.aspx) が、全体View に相当する
-コードビハインド (*.aspx.cs, *.aspx.vb) が、Controller に相当する
-画面を遷移するときは、Response.Redirect メソッドを使用して処理をリダイレクトする

-メリット
--従来の ASP.NET の経験がある人には、とっつきやすい可能性がある。
-デメリット
--Controller クラスの数が膨大になる可能性がある。

***全体View (1..*) <---> (1) Controller [#n9abe57a]
複数の 全体View に対して、1 つの Controller を対応させる考え方。

アプリケーションの
-機能や、
--=「全体View ごとに Controller を作成する方式」
-データ構造に
--=「[[スキャフォールディング方式>#z5e00de8]]」

対して、1 つの Controller を対応させる考え方。

-メリット
--まとまった業務ごとに Controller を作るので、Controller の数を抑えられる。
-デメリット
--複数の 全体View からの処理をすべて 1 つの Controller で受け付けるため、その Controller のコード量が多くなる可能性がある。


***スキャフォールディング(scaffolding)方式 [#z5e00de8]
たとえば、受注処理を行うアプリケーションを考えると、~
「受注作成画面」・「受注内容更新画面」・「受注削除画面」など、~
複数の 全体View に分かれていても、同じ「受注」業務=受注エンティティ~
に関するリクエストは 1 つの Controller が受け付ける、という考え方。

-(1 つの Model に対して、その Model に関するリクエストを受け付ける ~
1 つの Controller、および CRUD を行う 4 つの 全体View が作成される)

-スキャフォールディングの場合、M/V/C それぞれの多重度は、以下のようになる。
--全体View (4) <---> (1) Model~
(1 つの Model に対して、CRUD を行う 全体View がそれぞれ作成される)
--Controller (1) <---> (1) Model~
(1 つの Model に対して、その Model に関するリクエストを受け付ける Controller が 1 つ作成される)
--全体View (4) <---> (1) Controller~
(CRUD を行う 4 つの 全体View は、1 つの Controller にのみリクエストを送る)

-しかし、1 つの 全体View で、CRUD 全てを実現できる (CRUD ごとに 全体View が分かれない) 場合は、以下のようになる。~
--全体View (1) <---> (1) Model
--Controller (1) <---> (1) Model
--全体View (1) <---> (1) Controller

**モジュール化の要約 [#j2c8410a]
以下の2つの方式から選択する。
Controllerをどのような単位で作成するかにかかっている。

業務画面は、Modelに対応するCRUD画面を生成するスキャフォールディングと異なり~
Controllerが厳密に1つのModelに紐付かないため、画面単位のモジュール化のほうが適合するかもしれない。
***機能やデータ構造に対して 1 つの Controller を対応させる方式 [#td62a820]
-全体View (1..*) <---> (1) Model
-Controller (1) <---> (1..*) Model
-全体View (1..*) <---> (1) Controller

***スキャフォールディング方式 [#td62a820]
Model (0..1) <---> (1) View (1..*) <---> (1) Controller
***全体View ごとに Controller を作成する方式 [#se3008cd]
-全体View (1..*) <---> (1) Model
-Controller (1) <---> (1..*) Model
-全体View (1) <---> (1) Controller

***ASPXライクな1画面1モジュール方式 [#se3008cd]
Model (0..1) <---> View (1) <---> (1) Controller
*Controller の作成 [#ra660e99]
**モジュール化 [#t796c394]
[[モジュール化の要約>#j2c8410a]]で紹介した、
-[[機能やデータ構造に対して 1 つの Controller を対応させる方式>#td62a820]]
-[[全体View ごとに Controller を作成する方式>#se3008cd]]

*Controllerの作成 [#ra660e99]
何れかの方針に合わせて、Controllerを作成する。

**Actionの作成 [#m1334cd3]
**利用可能な属性 [#pb75e024]
***HTTP メソッド属性 [#qa67aa3b]
特定の HTTP メソッドのみを受け入れる属性を付与することができる。

***URLルーティング [#zed8012c]
ユーザーがブラウザーに URL を入力すると、MVC アプリケーションでは、~
RouteConfig.cs / .vb ファイルに定義されているルーティング規則~
を使用してURL が解析され、コントローラーのパスが特定される。
なお、Action MethodにHTTPメソッド属性を指定しなかった場合、~
Action Methodは、すべての HTTP メソッドを受け入れる。

-コントローラーは、要求を処理する適切なアクション メソッドを決定する。
-既定では、要求の URL は、コントローラー名とアクション名を含むサブパスとして扱われる。
AcceptVerbs 属性は、複数のHTTPメソッドを受け入れるAction Methodの定義に使用する。

***HTTP method [#qa67aa3b]
-AcceptVerbs 属性は、以下のように利用する。
 [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
 public ActionResult XXXXX(・・・) { ・・・ }
-以下は、AcceptVerbs 属性で使用できる列挙型の列挙子の一覧~
https://msdn.microsoft.com/ja-jp/library/system.web.mvc.httpverbs.aspx

-Get :
MVC 2 からはHttpGet, HttpPost, HttpPut, HttpDeleteという4つの属性が追加された。

--メソッド定義 : [HttpGet]メソッド属性を付与
-[HttpGet] メソッド属性
--概要
---Get メソッドのみ受け入れる。
---それ以外の HTTP メソッドは受け入れない(404 が返る)。

--ユースケース:
---Getで別画面に画面遷移する場合
--ユースケース
---Get で別画面に画面遷移する場合
---入力項目が無い状態で、同一画面内で状態遷移する場合

-Post :~

--メソッド定義 : [HttpPost]メソッド属性を付与
-[HttpPost] メソッド属性
--概要
---Post メソッドのみ受け入れる。
---それ以外の HTTP メソッドは受け入れない(404 が返る)。
--ユースケース
---フォームの入力項目を Controller に Post する場合。
---Post で別画面に画面遷移する場合。

--ユースケース :
---入力項目がある状態でのPostBackする場合。
---Postで別画面に画面遷移する場合。
-, etc.

-,etc. : ,etc.
***ActionName属性 [#mbf9d5ab]
Action Method名と、外部に公開するAction Nameとを別にする。

-メソッド属性を指定しない場合の動作~
全ての HTTP method を受け入れる。
例えば
|項番|Action Method名|ActionName|処理の内容|h
|1|Delete|Delete|削除画面の初期表示処理|
|2|DeleteConfirmed|Delete|削除処理の実行|

***引数 [#i5d9821b]
-マップの方法
***ValidateAntiForgeryToken属性 [#y1268547]
CSRF対策に使用する。~
複数ブラウザウィンドウ対応がなされているかどうかは未確認。

--POSTやGETのパラメタの名前と一致した引数を定義しておけば、自動的にマップされる。
---Get ならクエリ文字列のキー名
---Post ならフォームデータのキー名
-View
 @using (Html.BeginForm())
 {
     @* トークンを埋め込む *@
     @Html.AntiForgeryToken()
 }

--FormCollection を使う (Post の場合のみ)~
&lt;form&gt; の中身がコレクション型として保持されたもの。
-Controller
 // トークンを検証する
 [HttpPost, ActionName("Delete")]
 [ValidateAntiForgeryToken]
 public ActionResult DeleteConfirmed()
 {
     ・・・
 }

--モデルクラスを使う (Post の場合のみ)~
コントローラーとビューで、モデルクラスのデータを双方向バインディングしている場合に使用される。
-参考
--連載:ASP.NET MVC入門:第4回~
フィルタ属性による認証/キャッシュ/セキュリティ対策の実装 (5/5) - @IT~
http://www.atmarkit.co.jp/ait/articles/0908/14/news041_5.html
--ASP.NET のセキュリティ対策について考える - しばやん雑記~
http://blog.shibayan.jp/entry/20120526/1338001863
--ASP.NET の組み込み機能を活用し、Web 攻撃を回避する~
https://msdn.microsoft.com/ja-jp/library/ms972969.aspx

-HtmlHelperの生成するパラメタ~
HtmlHelperの生成するパラメタのうち、HtmlHelperが使用するものは~
メソッド引数にマップしない(そのパラメタを自分で使いたければ、マップしても構わない)。
*Model の作成 [#r127e540]

***戻り値 [#v19d2983]
[[アクションメソッドの結果として、クライアントに返す適切なビューを選択する。>#q7da2efc]]
**モジュール化 [#eba3e05a]

*Modelの作成 [#r127e540]
[[モジュール化の考え方>#qfa205f4]]のように、Model には 2 つの意味がある。

*Viewの作成 [#m019c385]
**Razer、ASPX の使い分け[#m195fa6e]
Razer、ASPX構文でModelを使ってHTMLを生成。
-アプリケーションの基礎となるデータ構造
--POCO として作成する。
--XXXXViewModelという名称を付与する。

ASPX と Razor の記述方法の比較
-そのデータを取得・加工する業務ロジック
--通常の業務ロジック・クラスとして作成する。

||ASPX|Razor|h
|インライン式 (プロパティの値を表示する場合など)|<%: Model.Property1 %>|@Model.Property1|
|インライン式 (エスケープ処理をスキップし、プロパティの値をそのまま表示する場合)|<%= Model.Property1 %>|@Html.Raw(Model.Property1)|
|コードブロック (ロジックを直接 View に記述する場合) (C#)|<% string str = "あいうえお"; %>|@{ string str = "あいうえお"; }|
|コードブロック (ロジックを直接 View に記述する場合) (VB)|<% Dim str As String = "あいうえお" %>|@Code&br;&nbsp;&nbsp;&nbsp;&nbsp;Dim str As String = "あいうえお"&br;End Code|
ココでは前者について言及する。

**利用可能な属性 [#yb8830b1]
System.ComponentModel.DataAnnotations属性により、

-検証機能
-[[テンプレート・ヘルパー>#s2b28732]]と呼ばれるHtmlヘルパー
-Controllerのスキャフォールディング生成

の動作を制御する事ができる。

-参考
--第3回 モデル・バインドとアノテーション検証の実装 - @IT~
http://www.atmarkit.co.jp/fdotnet/aspnetmvc3/aspnetmvc3_04/aspnetmvc3_04_01.html
--第6回 テンプレート機能でビュー開発を効率化 - @IT~
http://www.atmarkit.co.jp/fdotnet/aspnetmvc3/aspnetmvc3_07/aspnetmvc3_07_01.html
--ASP.NET MVC の ModelMetadata は奥が深い - しばやん雑記~
http://blog.shibayan.jp/entry/20120108/1326030354

***DataType属性 [#w26b6337]

型情報を指定することで、
-表示に関する制御属性
-汎用的な[[検証属性>#za53bd3d]]

として使用される。

 [DataType(DataType.XXXX)]

-参考

--DataType 列挙体 (System.ComponentModel.DataAnnotations)~
https://msdn.microsoft.com/ja-jp/library/system.componentmodel.dataannotations.datatype.aspx
---Password列挙子
---Text列挙子
---Url列挙子
---ImageUrl列挙子
---MultilineText列挙子
---EmailAddress	列挙子
---PhoneNumber列挙子
---PostalCode列挙子
---Currency列挙子
---CreditCard列挙子
---Date列挙子
---Time列挙子
---DateTime列挙子
---Duration列挙子
---Html列挙子
---Upload列挙子
---Custom列挙子

***DataTypeの派生の属性 [#q63930d1]
[[DataType属性>#w26b6337]]と同様に利用される。

-参考

--ASP.NET MVCのモデルでよく使う属性(アノテーション)リスト - Qiita~
http://qiita.com/mrpero/items/607c31895d77815a77cb

--DataTypeAttribute クラス (System.ComponentModel.DataAnnotations)~
https://msdn.microsoft.com/ja-jp/library/system.componentmodel.dataannotations.datatypeattribute.aspx
---CreditCard属性
---EmailAddress属性
---EnumDataType属性
---FileExtensions属性
---Phone属性
---Url属性

***DisplayName, Display属性 [#af7225e4]
表示名(Label表示を行なうHtmlヘルパーに使用される)

-DisplayName
--[DisplayName("xxxx")]

-Display
--Name
---[Display(Name = "xxxx")]
--ResourcesType(国際化対応用)
---[Display(Name = "xxxx", ResourceType = typeof(yyyy))]

***DisplayFormat属性 [#u40f1f5d]
フォーマットの指定。
 [DisplayFormat(DataFormatXXXX="YYYY")]

-DisplayFormatAttribute クラス (System.ComponentModel.DataAnnotations)~
https://msdn.microsoft.com/ja-jp/library/system.componentmodel.dataannotations.displayformatattribute.aspx
--DataFormatString(書式指定文字列)
--ApplyFormatInEditMode(編集モードで書式を適用するかどうか)
--NullDisplayText(null の場合表示するテキスト)
--ConvertEmptyStringToNull(空文字列をnullに変換)
--, etc.

***UIHint属性 [#kbd81af8]
-独自の表示/編集[[テンプレート・ヘルパー>#s2b28732]]を準備する。
-例えばDateTime型を指定したEditorForで~
使用するjQuery UIのDatepickerを適用する。

***DisplayColumn属性 [#dda2f14b]
-Model間のRelationを設定した際、Modelの表示名に使用しているColumn。
-Model間のRelationは、[[ナビゲーション・プロパティ>#zee4e783]]で設定する。

***検証属性 [#za53bd3d]
検証属性については、[[コチラ>#f5ad9690]]。

**ViewModelの作成方法 [#qe7b0732]

***[[ASP.NET MVCでDataTableを使用する。]] [#t66cb1ef]

***[[AutoMapper]]を使用する。 [#i0066a02]

*View の作成 [#m019c385]
**モジュール化 [#c1b7f428]

**Razer、ASPX の使い分け[#m195fa6e]
[[基本、Razer(主流)を使用する。>ASP.NET MVCの用語#z40de977]]

**BeginForm の使い分け [#sf5c2980]
-HTML(Ajax).BeginFormを記述(そもそもこれはFormタグを生成するヘルパ)
--ここで指定した名前のaction属性を持つFormが生成される。
--これがPOSTされると、その名称のコントローラーのActionに入る。
ASP.NET MVC には、&lt;form&gt; タグを生成する Htmlヘルパーが 2 種類ある。~
BeginForm ヘルパーは引数にコントローラー名、アクション名が付与でき、指定したアクションメソッドにリクエストを送ることができる。

-MicrosoftのASP.NET MVCのAjax.BeginFormは、~
クライアント・サイドのJavaScriptフレームワークとシームレスに連動しているので~
JavaのOSSフレームワークと比べて、かなり実装し易くトラブルも起き難くなっている。

***HTML.BeginForm [#y7008c56]
部分Viewの作成は共通化のため。
通常の &lt;form&gt; タグを生成する場合に使用する。

-全体更新が多数を占める場合(画面設計による)。
-全体更新が多数を占める場合 (アクションメソッドの結果として、View 全体を更新する場合)。

-レガシー技術で構築したい場合
--クライアント・サイドのJavaScriptフレームワークにより~
ブラックボックス化されておりトラブルシュートに心配がある場合がある。
--ただし、JavaのOSSフレームワークと比べてシームレスに連動しているので~
マイクロソフトのサポートを活用して解決できる可能性が高い。

-画面リフレッシュにより、リクエスト・レスポンスのステータスを明確にしたい場合。

***Ajax.BeginForm [#b0eaca55]
部分Viewの作成は更新範囲の定義のため。
&lt;form&gt; タグに Ajax リクエスト用の属性が付与され、リクエストが非同期で処理される。

-部分更新が多数を占める場合(画面設計による)。
-部分更新が多数を占める場合 (アクションメソッドの結果として、View の一部分のみを更新する場合)。

-サーバー側処理が非常に重い業務の場合(Ajax は非同期処理のため)。
-サーバー側処理が非常に重い業務の場合 (Ajax は非同期処理のため)。

-画面入力状態を保持したまま POST 送信したい場合
--ViewstateがサポートされないMVCで情報復元処理を割愛したい場合。
--[[ViewState>ASP.NET ViewState]]がサポートされない MVC で、情報復元処理を割愛したい場合。

-リクエスト・レスポンスのサイズを削減して、性能向上を図りたい場合。

-画面リフレッシュによる、画面のちらつき等をなくしたい場合。
-画面リフレッシュによる、画面のちらつきなどをなくしたい場合。

***参考 [#q5e2db0d]
-ajaxの使いどころ~
http://okwave.jp/qa/q8112782.html

-Html.BeginForm() vs Ajax.BeginForm() in MVC3 - CodeProject~
http://www.codeproject.com/Articles/429164/Html-BeginForm-vs-Ajax-BeginForm-in-MVC3

**Fromタグの切り方 [#j1aac0c9]
-1画面、1Form?
-1画面、複数Form?
**From タグの切り方 [#j1aac0c9]
画面設計によるが、以下を考慮する。
-1 View に対して 1 Form?
-1 View に対して複数 Form?

複数Formの場合はFormをネストさせないこと。~
#HTMLの仕様でFormのネストは禁止されている。
複数 Form の場合は Form をネストさせないこと。~
#HTML の仕様で Form のネストは禁止されている。

**HTML ヘルパーの使い分け [#c3297525]
Html.xxxx と Html.xxxxFor の2種類のHTML ヘルパーがある。
**Htmlヘルパーの使い分け [#f9430132]
***[[Htmlヘルパー(Html.xxxx と Html.xxxxFor>ASP.NET MVCの用語#o7472bbe]] [#c3297525]
-Html.xxxxFor~
--ポスト時にModelデータを復元する場合。
--例えばエラー発生時に、自画面の再表示(≒ポストバック)をする場合。

***Html.xxxx [#o7472bbe]
Html.TextBox("Category") のように、プロパティを文字列でマップ指定する場合は、"For" がつかない HTML ヘルパーを使用する。
-Html.xxxx~
上記以外は、Html.xxxxで良い。

***Html.xxxxFor [#b6d55f13]
Html.TextBoxFor(model => model.Category) のように、プロパティをラムダ式でマップ指定する場合は、"For" で終わる HTML ヘルパーを使用する。
***GridView的な一覧(グリッド)生成用のHtmlヘルパー [#j629d667]
ASP.NET MVC で一覧(グリッド)のある View を作成する場合、以下の 3 種類が考えられる。

-...Forを使用してマップ指定すると、ViewとModel間で双方向バインディングされる。
-[[WebGrid>ASP.NET MVCのWebGrid]] クラスを使用する~
ソートやページングが容易に実装できる反面、レンダリング部分は多少ブラックボックスになる

-とは言え、HTTPを経由しての双方向バインディングになるので、~
処理方式的には、以下の様な処理シーケンスになる。
--POST時に、Formsの情報を自動的にModelに復元する。
--Viewでは復元されたModelから情報を取得して画面を生成する。
-&lt;table&gt; タグを自前で生成し、&lt;tr&gt; タグをループで実装する~
ASP.NET の Repeater コントロールのような処理の実装方法(Razorなぶん楽)。

***使い分け [#uc043058]
以下のケースで使い分ける。
-jqGrid など、OSS の JavaScript ライブラリを使用する。

-ASPXライクな1画面1モジュール方式か?
-スキャフォールディング方式か?
-BeginFormの種類
--[[HTML.BeginForm>#y7008c56]]」か?
--[[Ajax.BeginForm>#b0eaca55]]」か?
***テンプレート・ヘルパー(テンプレートに対応したHtmlヘルパー) [#s2b28732]
DisplayForやEditorForなどモデル定義に応じて出力を自在に変えられるHtmlヘルパー。

個人的には、
-ASPXライクな1画面1モジュール方式
-[[HTML.BeginForm>#y7008c56]]
-Htmlヘルパー
--DisplayFor、DisplayForModel:データの表示
---DisplayFor:
---DisplayForModel:Model単位にテンプレート・ヘルパーを決定する。

の場合に最も適合すると考える。
--EditFor、EditForModel:データ編集項目の生成
---EditFor:
Htmlヘルパーの第二引数でテンプレート・ヘルパーを指定できる。~
UIHint属性で指定したテンプレート・ヘルパーが使用される。~
属性の優先度は、UIHint属性 -> DataType属性 -> 実際のデータ型
---EditForModel:Model単位にテンプレート・ヘルパーを決定する。

***グリッドの生成 [#j629d667]
WebGridのHTML ヘルパーを使用すると、MVCなのにHTML感を味わえないので、Loopで実装することもある。
-テンプレート・ヘルパー名とテンプレート・ヘルパー配置場所
--DisplayTemplates
---~/View/Shared/DisplayTemplates/DataType名 or Model名.cshtml
---~/View/Controller名/DisplayTemplates/DataType名 or Model名.cshtml
--EditorTemplates
---~/View/Shared/EditorTemplates/DataType名 or Model名.cshtml
---~/View/Controller名/EditorTemplates/DataType名 or Model名.cshtml

**View [#j11c45d9]
***全体View [#od7cef82]
-Controller上のActionメソッド(のリージョン)を右クリック、
-Viewを選択するとウィザードが起動する。
-参考
--[Razor] - Build Insider
---テンプレート関連のビューヘルパー|テンプレートの標準の挙動~
https://www.buildinsider.net/web/bookaspmvc5/040401
---テンプレートのカスタマイズ|テンプレートを決定する方法~
https://www.buildinsider.net/web/bookaspmvc5/040402
---モデル単位にテンプレートを決定する - DisplayForModel/EditorForModelメソッド~
https://www.buildinsider.net/web/bookaspmvc5/040404

-Viewテンプレート(スキャフォールディング)を選択
***Html.Hidden または Html.HiddenFor [#mcb3c672]
タイムスタンプ型など、ユーザに見えない情報だが~
内部処理に必要な情報を引き継ぐ場合に使用する。

--Modelへの対応付け~
テンプレートを使用した場合、対応した自動生成がされる。
***カスタムHtmlヘルパー(カスタム・コントロールみたいな) [#uf401f54]

--オプション
---部分View
---スクリプト・ライブラリ参照
---レイアウト・ページ(個別設定可能)
-参考
--ASP.NET MVC 5  開発メモ: ASP.NET MVC 5 についての開発メモである。ただしVB.NETがベース > ビューヘルパーを自作する~
http://aspmvc.tokumori-domain.com/view/crt_viewhelper/

***部分View [#j4280e7b]
-Viewのフォルダ(Controller名)を右クリック、
-Viewを選択するとウィザードが起動する。
--第6回 テンプレート機能でビュー開発を効率化(3/3) - @IT~
http://www.atmarkit.co.jp/fdotnet/aspnetmvc3/aspnetmvc3_07/aspnetmvc3_07_03.html

-ウィザードの入力
--_XXXViewと名称を付与する。
--部分Viewにチェック入れる。
**画面遷移 [#ycae9af6]
[[モジュール化の要約>#j2c8410a]]で紹介した、
-[[スキャフォールディング方式>#td62a820]]、
-[[全体View ごとに Controller を作成する方式>#se3008cd]]

-親画面から部分Viewを呼び出す。
--親Viewからは、HTMLヘルパのHtml.Partialを使用する。
--PartialViewNameとModelを引数に取る~
親と同じModelを渡すか?Model.Modelを渡すか?どちらでもOK。
共に、画面遷移の処理フローは以下のようになる。

-Ajax.BeginFormの場合、親画面から部分ViewをDIVで囲っておく。
***処理フロー [#t080759a]
+View から、対応する Controller にリクエストを送る
+Controller はリクエストを受け付け、Model に処理を指示する
+Model は業務ロジックを実行し、データを更新する
+Controller は View に表示を指示する

*画面遷移の考え方 [#q3d2aae4]
「[[ルーティング>ASP.NET MVCの用語#abe121d3]]」で説明したとおり、~
URLでController+Actionを指定すると指定のControllerのActionが実行される。~
#ただし、Actionを省略した時は、Index(既定のAction)が呼ばれる。
***実装方法 [#v4250bf7]
なお、1つの View が、任意の Controller にPOSTリクエストを送る~
[[ASP.NET Web Forms]]の「ページ間ポスティング」的な実装も書けるが、~
View と Controller の関係が複雑になるのでオススメしない。

**画面遷移のメソッド [#q7da2efc]
***Viewの選択 [#vfdf6f42]
下記ヘルパ・メソッドを使用する。
従って、上記の「4.」で、''どの View に表示の指示をするか''によって、~
使用する ActionResult クラスを下記のように変える様に実装する。

-Return View("Result")
--基本的には「[[HTML.BeginForm>#y7008c56]]」の場合に使用する。
--ControllerからViewResultを選択して返す(通常は自画面を選択)。
--Ajax.BeginFormの場合は、画面の初期表示などにも用いられる
-その Controller に対応する View に、表示を指示する場合
--ViewResult を使用する
-別の Controller に対応する View に、表示を指示する場合
--RedirectToActionResult または RedirectToRouteResult を使用する

-Return PartialView("Result")
--基本的には「[[Ajax.BeginForm>#b0eaca55]]」の場合に使用する。
--ControllerからPartialViewResultを選択して返す。
**モバイル対応 [#h79b3a91]
***Mobil Template [#q17cb912]
「モバイル アプリケーション」テンプレートを使用して、~
モバイルデバイス向けアプリケーションを作成できる。~
このテンプレートでは、jQuery Mobile をベースとしており、~
タッチ操作に最適化した UI を構築できる。

***画面遷移 [#b9d4724d]
-Redirect遷移方式~
--画面に対応するコントローラーを選択する。
--下記のRedirect系ヘルパ・メソッドを使用する。
***DisplayModes [#db369cfe]
Bootstrapによるレスポンシブデザインに頼らず、~
PC 向けサイト、モバイル向けサイトの画面を分けるアプローチ。

-Redirect系ヘルパ・メソッド
--Return Redirect
---指定されたURLにリダイレクト。
---Return Redirect("http://www.wings.msn.to/");
-DesktopかMobilかは、UserAgentやUserHostAddressを使用して判別している。

--Return RedirectToAction
---アクション名、コントローラー名、ルート値を使用して、指定されたアクションにリダイレクト。
---Return RedirectToAction("Index")
-通常、XXXXX.cshtmlとXXXXX.Mobil.cshtmlの2つのViewスクリプトを作成する。~
上記は、マスタページや部分ViewなどのViewスクリプトにも適用することができる。
--XXXXX.cshtml (PC 向けサイト)
--XXXXX.Mobil.cshtml (モバイル向けサイト)

--Return RedirectToRoute
---ルート名とパラメータ値を引数とし、適切なルーティングフレンドリなURLへリダイレクト
---RedirectToRoute("View Product", new { ProductName = <商品名> }); 
-以下のコードを追加してデバイスごとにXXXXX.YYYYY.cshtmlとViewスクリプトを追加する。
--Global.asax の Application_Start メソッドに定義する。
 protected void Application_Start()
 {
     (中略)
 
     DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone ")
     {
         ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf("iPhone ", StringComparison.OrdinalIgnoreCase) >= 0)
     });
 }

**画面遷移の方法 [#ycae9af6]
以下の方式が考えられる。
この時、
-「XXXXX.cshtml」と同じフォルダに
-「XXXXX.''iPhone''.cshtml」を作成し、

***POSTでView選択 or 画面遷移 [#tc702cd7]
-BeginFormに任意のController&Actionを指定する。
-POST遷移後、Actionの中でReturn View("Result") ヘルパ・メソッドを使用して画面遷移する。
iPhone 向けのレイアウトを定義すると、

***自ControllerにPOST後にView選択 or 画面遷移 [#qba5f1f4]
-BeginFormに自Controller&任意のActionを指定する。
 http://server/application/Controller/Index/id

-自ControllerにPOST後、任意のActionの中で
--View選択(Transfer的な)~
Return View("Result") ヘルパ・メソッドを使用して画面遷移する。
--画面遷移(Redirect)~
Return RedirectToAction ヘルパ・メソッドを使用して画面遷移する。
という同じ URL に対し、
-PC のブラウザからアクセスした場合、「Index.cshtml」が使用され、
-iPhone からアクセスした場合は「Index.''iPhone''.cshtml」が使用されるようになる。

***例外的な遷移 [#nda50fd0]
-例外的にクライアントからGETで遷移するケースもある。
-Link, IFRAME, window.open, etc.
**その他 [#ne32fd7c]

**URLと画面 [#p47f7c6e]
***View (1..*) <---> (1) Controller(スキャフォールディング)+ POST遷移 [#f5f1cb0f]
URLは
-Controllerにだけ対応する。
-Viewにまでは対応しない。
***WebViewPage [#nf2840bc]
このクラスで設定・追加したプロパティが、~
各Viewファイル(.cshtmlや.vbhtml)の開発時に使用出来るようになる。

***View (1) <---> (1) Controller(ASPXライク)+ 自ControllerにPOST後に遷移 [#uaea1303]
URLは
-Controllerに対応する。
-Viewにまで対応する。
-ASP.NET MVC 5 / Core MVCで独自のビューページのクラスを使用する - Qiita~
https://qiita.com/taiga_takahari/items/1c788ac91b62324a9140

*フォルダ構成 [#c0d7785c]
**フォルダ分けの意味 [#f6c4f503]
-グルーピングのため。
-名前空間が分かれる。
*情報の持ち回り・状態管理方式 [#i6db0cb0]

**各フォルダについて [#k32c9ab6]
***App_Start [#s308455d]
-初期設定(起動時)を行うモジュールが配置される。
-例えば、RouteConfigはURLの設定を行う。
**[[ViewState>ASP.NET ViewState]] [#l314ae9e]
利用不可能

***Contents [#x1809e9f]
-CSSはココに置く。
-フォルダ構成は自由
-規定のものは変更しない(BundleConfigで使用しているため)。
-必要であれば、[[ViewState>ASP.NET ViewState]]相当の状態保存処理を独自実装する必要がある。

***Scripts [#d30cbb78]
-Javascriptはココに置く。
-フォルダ構成は自由
-規定のものは変更しない(BundleConfigで使用しているため)。
-[[For付きのHtmlヘルパー(Html.xxxxFor)>ASP.NET MVCの用語#o7472bbe]]を使用すれば、~
双方向バインディングによりポストバックの範囲で値は維持される)。

***Models [#j9f85022]
-Modelはココに置く。
-フォルダ構成は自由
**Hidden [#a026afb5]
使用可能

***Controllers [#i31b0bdb]
-Controllerはココに置く。
-フォルダ構成は自由(ただし、フォルダはURLに反映されない)
**Session [#je17aeb2]
使用可能

-種類
--EntityFramework~
EntityFrameworkを使用する場合に選択する。
*検証機能 [#za7f960c]
Action メソッド内で個別にチェックロジックを実装するか、~
ModelMetadataを使用したチェックが可能。

--空~
Action→Index(既定のAction)が生成される。
**Model側 [#qd38a035]

--スキャフォールディング~
スキャフォールディングに対応したActionが生成される。
***検証属性 [#f5ad9690]
以下の属性を使用して検証可能。

-Controllers.Action~
HTTPのGETもPOSTも処理できる(メソッド属性で制限できる)。
|項番|属性|概要|h
|1|[[DataType属性>#w26b6337]](enumDataType, errmsg)|指定のデータ型に変換可能か|
|2|Required属性(errmsg)|必須入力|
|3|StringLength属性(max, errmsg)|文字列の最大長|
|4|MaxLength属性(max, errmsg)|文字列の最大長|
|5|MinLength属性(min, errmsg)|文字列の最小長|
|6|Range属性(min, max, errmsg)|範囲|
|7|RegularExpression属性(pattern, errmsg)|[[正規表現]]|
|8|MembershipPassword属性()|パスワード|
|9|Compare属性(targetname, errmsg)|比較(e-mailやpasswdの確認用フィールドに使用する)|
|10|Remote属性(actionMethod, errmsg)|Ajaxを使用したチェック|
|11|CustomValidation属性()|カスタム|

***Views [#w1a844a4]
-Viewはココに置く。
各属性の errmsgプロパティに何も設定しなくても既定でエラーメッセージが出る。

-Viewsの下位フォルダは作成できない。
--Controller名に対応するフォルダが自動的に生成される。
--補足:XXXXControllerXXXXという所がController名
-参考
--ASP.NET MVCのモデルでよく使う属性(アノテーション)リスト - Qiita~
http://qiita.com/mrpero/items/607c31895d77815a77cb
--よく使われる入力検証をまとめてみる - しばやん雑記~
http://blog.shibayan.jp/entry/20110708/1310132392

-規定のページ
--_ViewStart.cshtml
---規定の設定をする、個別に上書き(変更)可能。
---規定では、Layoutに_Layout.cshtmlを設定している。
***[[DataType属性>#w26b6337]] [#mdc47170]
[[DataType属性>#w26b6337]]も[[検証属性>#f5ad9690]]として機能する。

--_Layout.cshtml
---規定のマスター・ページ(レイアウト・ページ)
---Sharedの_Layout.cshtml(規定のレイアウト)
-参考

***Area [#re760150]
なお、Areaを作るとViewsも含めたサブシステム単位のフォルダ分割ができる。~
以下、App_Startのマップルートが追加されるような感じ。
--DataType 属性による検証~
http://surferonwww.info/BlogEngine/post/2016/03/08/validation-by-datatypeattribute-and-default-error-message.aspx

*情報の持ち回り・状態管理方式 [#i6db0cb0]
**Viewstate [#s3a7d336]
利用不可能(必要であれば、自前で実装する必要がある)
***CustomValidation属性 [#f553a183]
ざっくり、以下のようにして、CustomValidation属性を使用する。

**Hidden [#o0afdc6f]
Formの定義・分割が可能なため、持ち回りも共通化困難。
-単項目チェック処理~
--プロパティにCustomValidation属性を設定し、呼び出す検証メソッドと関連付ける。
--CustomValidation属性に設定した、staticの検証メソッドを定義する。
--検証メソッドでは、検証結果として、ValidationResultを返す。

*チェック処理方式 [#hc015ceb]
**クライアント [#i39f251f]
JavaScriptでのチェック
-関連チェック処理~
--モデルにCustomValidation属性を設定し、呼び出す検証メソッドと関連付ける。
--CustomValidation属性に設定した、staticの検証メソッドを定義する。
--検証メソッドでは、検証結果として、ValidationResultを返す。

**サーバ [#k1290bb8]
Action内でのチェック
***自作Validation属性 [#l98ac398]
ざっくり、以下のようにして、自作Validation属性を定義して使用する。

**モデルにチェックコードを実装 [#k61bb861]
色々あってよく解らない。
-単項目チェック処理~
--プロパティに自作Validation属性を指定して検証パラメタやエラーメッセージを指定する。

-自作Validation属性の作成
--ValidationAttributeクラスを継承した自作Validationを定義する。

--コンストラクタを実装~
検証パラメタとエラーメッセージを準備(必要に応じてパラメタライズ)

--メソッドをoverrideして実装する。
---FormatErrorMessageメソッドでエラーメッセージを生成
---IsValidメソッドで検証処理を実装し、検証結果として、boolを返す。

-自作Validation属性をクライアント側検証に対応させる。

--IClientValidationインターフェイスを実装する。
---属性とViewの橋渡しを行なうGetClientValidationRuleメソッドを実装する。
---GetClientValidationRuleメソッドでは、IEnumerable<ModelClientValidationRule>を返す。
---これにより、検証名に対応する検証パラメタとエラーメッセージがHTML側に属性として出力される。

--ModelClientValidationRuleのプロパティ~
https://msdn.microsoft.com/ja-jp/library/system.web.mvc.modelclientvalidationrule_properties.aspx
---ValidationType(検証名)
---ValidationParameters(検証パラメタのKey/Value)
---ErrorMessage(エラーメッセージ)

--jQuery Validation プラグインとの関連付け。~
検証ロジックとを独自jsファイルに定義する。
---$.Validator.addMethod('検証名'~、
---$.validator.unobtrusive.adapters.addSingleVal('検証名', '検証パラメタのKey');。
---BundleConfig.csに、この独自jsファイルをjqueryvalにincludeするバンドル定義を追加する。

***IValidatableObjectの実装 [#z830ac70]
ざっくり、以下のようにして、IValidatableObjectを使用する。~
複数の検証結果を返せるのは、IValidatableObjectだけである。

-関連チェック処理(IValidatableObject)
--モデルでIValidatableObjectを実装してIValidatableObject.Validateメソッドを実装する。
--検証メソッドでは、検証結果として、IEnumerable<ValidationResult>を返す。

**Controller側 [#y0986437]
***検証タイミング [#gea275d0]
Action Methodの実行前に、[[モデル・バインディング>ASP.NET MVCの用語#t62a5795]]が行われたタイミング。

***ModelStateDictionary [#bec6ea56]
-概要
--Controller.ModelStateでアクセスできる。
--モデルの状態とモデル・バインディングの検証結果を含む。

-Property
--IsValid プロパティ~
モデル・バインディングの検証結果として、モデルの有効・無効を返す。
--Keysプロパティ~
--Valuesプロパティ~

-Method
--ModelState.AddModelError()~
エラー情報を追加する。

**View側 [#za24022f]
***サーバ側 [#n811879d]

-Method
--Html.ValidationSummary~
すべての検証結果のエラー メッセージを要約する。
--Html.ValidationMessage~
個々の検証結果のエラー メッセージを表示する。
--Html.ValidationMessageFor~
個々の検証結果のエラー メッセージを表示する。

***クライアント [#i39f251f]
-検証後に適用されるCSSクラス~
これらのCSSクラスをSite.cssファイルに定義しておく。
--validation-summary-errors~
ValidationSummaryメソッドによって出力されたメッセージの<div>要素(エラー有)
--validation-summary-valid~
ValidationSummaryメソッドによって出力されたメッセージの<div>要素(エラー無)
--field-validation-error~
ValidationMessageメソッドによって出力されたメッセージの<span>要素(エラー有)
--field-validation-valid~
ValidationMessageメソッドによって出力されたメッセージの<span>要素(エラー無)
--input-validation-error~
検証エラーが発生した要素

-JavaScript でのクライアント側検証~
--[[jQuery Validation プラグイン>https://jqueryvalidation.org/]]なども使用可能。
--Controller追加で、[[スキャフォールディング>#e701b267]]する際、~
スクリプトライブラリの参照にチェックを入れるとJavaScriptライブラリをインポートできる。

**appSettings [#p175e137]
***クライアント側検証の無効化 [#g8e7a85a]
[[CustomValidation属性>#f553a183]]ではクライアント側検証が実行されない。~
整合性をとるために、クライアント側検証の無効化を行なう。

 <add key="ClientValidationEnabled" value="false" />

若しくは、[[自作Validation属性>#l98ac398]]にクライアント側検証を実装する。

***控えめなJavaScript [#d50074a3]
クライアント側検証に「控えめなJavaScript」のパラダイムが導入されている。
-*.htmlファイル側にJavaScriptではなく、属性を書く。
-JavaScriptは*.jsファイル側に書いて、HTMLとJavaScriptを分離する。
-「控えめなJavaScript」は以下のパラメタで制御できる。

 <add key="UnobtrusiveJavaScriptEnabled" value="true"/>

-控えめなJavaScript - Wikipedia~
https://ja.wikipedia.org/wiki/%E6%8E%A7%E3%81%88%E3%82%81%E3%81%AAJavaScript

**参考 [#j5f7111c]
-方法: DataAnnotations 属性を使用してモデル データを検証する~
https://msdn.microsoft.com/ja-jp/library/ee256141.aspx

-お楽しみはこれからだ!
--ASP.NET MVC RCの入力検証~
http://takepara.blogspot.jp/2009/02/aspnet-mvc-rc.html
--強力になったDefaultModelBinder~
http://takepara.blogspot.jp/2009/02/defaultmodelbinder.html
--DataAnnotationsだけでの入力検証の盲点~
http://takepara.blogspot.jp/2009/02/dataannotations.html

-こんなこともできるもよう(Entity Frameworkが必要)。
-[[Entity Framework>#g04871bf]]と検証処理。
--ASP.NET MVC 3における検証まわりの改善点 (3-4):CodeZine~
http://codezine.jp/article/detail/6176?p=3
--ASP.NET MVC 4 ことはじめ(5)モデルと足場 - アーキテクチャをスマートに。~
http://d.hatena.ne.jp/architect-wat/20130512/1368360044

*スキャフォールディング [#e701b267]
**概要 [#g794a3ae]
スキャフォールディング(Scaffolding)。~
日本語で「足場」、「骨組み」の意味。

-M(Model)を元に、
--C(Controller)
---CRUDを行うAction Method
--V(View)

>を自動で生成する機能。

-通常、
--CRUDのAction Methodだけが自動生成される。
--[[Entity Framework>#g04871bf]]によるデータ操作を行う場合、~
Action Methodに加えて View も自動生成できる。

-その他
--[[WebFormでもサポートされている>http://blog.shibayan.jp/entry/20130219/1361281202]]。

**M(Model) [#d93a335a]
-使用するModelを選択する。
-Modelの新規作成も可能

***[[設定する属性>#yb8830b1]] [#p879b91f]

***[[ナビゲーション・プロパティ>Entity Framework#gc07c222]] [#zee4e783]

**C(Controller) [#jf4991ce]
-M(Model)の複数形 + Controllerという名称になる。

-Action Method
--Index
--Details
--Create
--Edit
--Delete

**V(View) [#te3ce747]
-[[Entity Framework>#g04871bf]]を使用すると、以下のようにViewまで自動生成される。
-また、[[Entity Framework>#g04871bf]]を使用しない場合も、個別に、~
ModelMetadataを定義したModelを指定しView追加(スキャフォールディング)ができる。

|項番|View名|対応するAction Method名|使用されるTemplate名|h
|1|Index.cshtml|Index|List|
|2|Details.cshtml|Details|Details|
|3|Create.cshtml|Create|Create|
|4|Edit.cshtml|Edit|Edit|
|5|Delete.cshtml|Delete|Delete|

**テンプレートをオーバーライド [#yb615acb]
-ASP.NET MVC - 既定のスキャフォールディング テンプレートをオーバーライドする~
https://msdn.microsoft.com/ja-jp/magazine/dn745864.aspx

*ModelMetadataを使用した開発 [#d39da4a0]
**[[検証機能>#za7f960c]] [#ya808897]
**[[スキャフォールディング>#e701b267]] [#ya2bec28]

*脆弱性 [#jd31de6d]
**サニタイジング [#m59baf7f]
-HTMLヘルパーを使用すれば自動。
-Response.Writeの場合は自前。
-Htmlヘルパーを使用すると、自動的にサニタイジングが行われる。
-Model のプロパティを直接 View に表示する場合は、自前でのサニタイジングが必要。

**リクエスト検証 [#ra245005]
-requestValidationModeをMVCでも利用可能。~
-requestValidationMode を MVC でも利用可能。~
http://stackoverflow.com/questions/6206540/what-does-requestvalidationmode-2-0-actually-do

*認証 [#i72e16ec]
[[ASP.NET MVC]]のテンプレートでは、
-[[ASP.NET Identity]]を使用するが、
-従来の、基本的な、[[ASP.NET Forms認証]]も使用可能。

**[[ASP.NET Forms認証]] [#ke4d524f]
-ASP.NET MVC で フォーム認証 の実装方法~
https://garafu.blogspot.jp/2013/11/aspnet-mvc.html

**[[ASP.NET Identity]] [#q7a423a0]
-[[ASP.NET Forms認証]]より高度な認証基盤。

-また、[[ASP.NET Identity]]を使用すると、~
[[OAuth]]のクライアント & サーバ機能を実装できる。

--[[OAuth]]のクライアント : [[ASP.NET Identityの外部ログイン]]

--[[OAuth]]のサーバ : [[ASP.NET IdentityのOAuth2によるSTS実装]]

*その他 [#fdc8ad5c]

**[[Entity Framework]] [#g04871bf]

**[[ASP.NET Web API]] [#s5b3bcda]

**[[ASP.NET SPA]] [#z1ff5f99]

----
Tags: [[:.NET開発]], [[:ASP.NET]], [[:ASP.NET MVC]]


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS