[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]] -[[ASP.NET MVC に戻る>ASP.NET MVC]] * 目次 [#n8bb5f94] #contents *概要 [#qe050a8a] *モジュール化の考え方 [#qfa205f4] まず、Model と View と Controller の役割について整理する。 -Model: アプリケーションの基礎となるデータ構造、およびそのデータを取得・加工する業務ロジック -View: Model が保持するデータを参照し、ユーザーに表示するもの -Controller: ユーザーからの入力を受け取り、Model に対してデータの取得・加工を指示する。~ その結果を受けて、View に表示を指示する。 **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 へのみリクエストを送る。~ 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 に分かれていても、同じ「受注」業務に関するリクエストは 1 つの Controller が受け付ける、という考え方。~ [[スキャフォールディング(scaffolding)>ASP.NET MVCの用語#e701b267]]が、この考え方を採用している。~ (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 -メリット --まとまった業務ごとに Controller を作るので、Controller の数を抑えられる。 -デメリット --複数の View からの処理をすべて 1 つの Controller で受け付けるため、その Controller のコード量が多くなる可能性がある。 **モジュール化の要約 [#j2c8410a] CRUD を 1 つの View で行うか?View を分けるか?など、画面設計にも関係するので、メリット/デメリットを考慮の上、どちらを採用するかを決定する。~ ***スキャフォールディング方式 [#td62a820] -View (1..*) <---> (1) Model -Controller (1) <---> (1..*) Model -View (1..*) <---> (1) Controller ***View ごとに Controller を作成する方式 [#se3008cd] -View (1..*) <---> (1) Model -Controller (1) <---> (1..*) Model -View (1) <---> (1) Controller *Controller の作成 [#ra660e99] **Action の作成 [#m1334cd3] ***URL ルーティング [#zed8012c] ユーザーがブラウザーに URL を入力すると、RouteConfig.cs / .vb ファイルに定義されているルーティング規則を使用してURL が解析され、コントローラーのパスが特定される。 コントローラーは、要求を処理する適切なアクション メソッドを決定する。 既定では、以下のように URL はコントローラー名とアクション名を含む必要がある。~ ここで、「id 値」とはアクションの引数名のことであり、アクションが「id」という名前の引数を持つ場合、URL に記述することでアクションの引数にその値を渡すことができる。~ ただし、アクション名と id 値は省略可能で、アクション名を省略すると、Index アクションが実行される。 http://(サーバー名)/(コントローラー名)/(アクション名)/(id 値) ***アクションメソッドと HTTP メソッド [#qa67aa3b] アクションメソッドには、特定の HTTP メソッドのみを受け入れる属性を付与することができる。 -[HttpGet] メソッド属性 --概要 ---Get メソッドのみ受け入れる。 ---それ以外の HTTP メソッドは受け入れない(404 が返る)。 --ユースケース ---Get で別画面に画面遷移する場合 ---入力項目が無い状態で、同一画面内で状態遷移する場合 -[HttpPost] メソッド属性 --概要 ---Post メソッドのみ受け入れる。 ---それ以外の HTTP メソッドは受け入れない(404 が返る)。 --ユースケース ---フォームの入力項目を Controller に Post する場合。 ---Post で別画面に画面遷移する場合。 なお、メソッド属性を指定しなかった場合、そのアクションメソッドはすべての HTTP メソッドを受け入れる。 ***リクエストデータと引数の関連付け [#i5d9821b] -マップの方法 --POST や GET のパラメタの名前と一致した引数を定義しておけば、自動的にマップされる。 ---Get ならクエリ文字列のキー名 ---Post ならフォームデータのキー名 --FormCollection を使う (Post の場合のみ)~ <form> の中身がコレクション型として保持されたもの。 --モデルクラスを使う (Post の場合のみ)~ コントローラーとビューで、モデルクラスのデータを双方向バインディングしている場合に使用される。~ (双方向バインディングについては、[[HTML ヘルパーの使い分け>#c3297525]]を参照。) ***戻り値 [#v19d2983] アクションメソッドの結果として、クライアントに返す適切なビューを選択し、表示を指示する。~ 詳細は[[アクションメソッドの戻り値>#q3d2aae4]]を参照。 *Model の作成 [#r127e540] [[モジュール化の考え方>#qfa205f4]]のように、Model には 2 つの意味がある。 -アプリケーションの基礎となるデータ構造~ POCO として作成する。 -そのデータを取得・加工する業務ロジック~ 通常の業務ロジッククラスとして作成する。 *View の作成 [#m019c385] **Razer、ASPX の使い分け[#m195fa6e] View には、Model のプロパティ参照用、if 文や for 文などの制御用にサーバー処理を埋め込むことができる。~ サーバー処理の記法に、Razer 構文、ASPX 構文がある。 ||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; Dim str As String = "あいうえお"&br;End Code| **BeginForm の使い分け [#sf5c2980] ASP.NET MVC には、<form> タグを生成する HTML ヘルパーが 2 種類ある。~ BeginForm ヘルパーは引数にコントローラー名、アクション名が付与でき、指定したアクションメソッドにリクエストを送ることができる。 ***HTML.BeginForm [#y7008c56] 通常の <form> タグを生成する場合に使用する。 -全体更新が多数を占める場合 (アクションメソッドの結果として、View 全体を更新する場合)。 -画面リフレッシュにより、リクエスト・レスポンスのステータスを明確にしたい場合。 ***Ajax.BeginForm [#b0eaca55] <form> タグに Ajax リクエスト用の属性が付与され、リクエストが非同期で処理される。 -部分更新が多数を占める場合 (アクションメソッドの結果として、View の一部分のみを更新する場合)。 -サーバー側処理が非常に重い業務の場合 (Ajax は非同期処理のため)。 -画面入力状態を保持したまま POST 送信したい場合 --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 View に対して 1 Form? -1 View に対して複数 Form? 複数 Form の場合は Form をネストさせないこと。~ #HTML の仕様で Form のネストは禁止されている。 **HTML ヘルパーの使い分け [#c3297525] Html.xxxx と Html.xxxxFor の2種類のHTML ヘルパーがある。 ***Html.xxxx [#o7472bbe] Html.TextBox("Category") のように、プロパティを文字列でマップ指定する場合は、"For" がつかない HTML ヘルパーを使用する。~ この場合、''Model から View への一方向バインディング''となる。 ***Html.xxxxFor [#b6d55f13] Html.TextBoxFor(model => model.Category) のように、プロパティをラムダ式でマップ指定する場合は、"For" で終わる HTML ヘルパーを使用する。 この場合、''Model と View との双方向バインディング''となる。 ただし、HTTP を経由しての双方向バインディングになるので、処理方式的には、以下のような処理シーケンスになる。 --POST 時に、Html.TextBoxFor などへの入力値を、自動的に Model に復元する。 --Controller は、復元された Model から情報を取得して処理を行う。 ***使い分け [#uc043058] 上記を踏まえて、M/V/C の多重度、および BeginForm を使い分ける。 -M/V/C の多重度 --View ごとに Controller を作成する方式か? --スキャフォールディング方式か? -BeginForm の種類 --[[HTML.BeginForm>#y7008c56]]」か? --[[Ajax.BeginForm>#b0eaca55]]」か? 個人的には、 -View ごとに Controller を作成する方式 -[[HTML.BeginForm>#y7008c56]] が良いのではないかと考える。 ***グリッドの生成 [#j629d667] ASP.NET MVC でグリッドのある View を作成する場合、以下の 3 種類が考えられる。 -[[WebGrid>https://msdn.microsoft.com/ja-jp/library/system.web.helpers.webgrid.aspx]] クラスを使用する~ ソートやページングが容易に実装できる反面、レンダリング部分は多少ブラックボックスになる -$lt;table$gt; タグを自前で生成し、<tr> タグをループで実装する~ ASP.NET の Repeater コントロールのようなもの -jqGrid など、OSS ライブラリを使用する **View [#j11c45d9] View には、画面全体を表す「全体 View」と、画面の一部分のみを表す「部分 View」がある。~ 部分 View は、「Partial View」ともいわれ、以下の用途で使われる。 -画面の共通化のため~ ASP.NET のユーザーコントロールのように、共通的な画面コンポーネントを部品化しておくもの。 -Ajax.BeginForm の部分更新の範囲を表すため~ Ajax.BeginForm を使用した非同期処理の場合、部分更新の範囲を部分 View で定義する。 *アクションメソッドの戻り値 [#q3d2aae4] Controller のアクションメソッドは、[[ActionResult>https://msdn.microsoft.com/ja-jp/library/system.web.mvc.actionresult.aspx]] クラスのオブジェクトを返す必要がある。~ ActionResult クラスには、View への指示内容によって、主に以下の種類が存在する。 |種類|概要・用途|コード例|h |ViewResult|全体 View の表示を指示する。&br();基本的には [[HTML.BeginForm>#y7008c56]] の場合に使用する。|return View("Result");&br();("Result" は全体 View 名)| |PartialViewResult|部分 View の表示を指示する。&br();基本的には [[Ajax.BeginForm>#b0eaca55]] の場合に使用する。|return PartialView("Result");&br();("Result" は部分 View 名)| |RedirectResult|指定した URL にリダイレクトする場合に使用する。|return Redirect("http://www.wings.msn.to/");| |RedirectToActionResult|指定した Controller, Action にリダイレクトする場合に使用する。|return RedirectToAction("Index");| |RedirectToRouteResult|指定したルート名にリダイレクトする場合に使用する。|return RedirectToRoute("View Product", new { ProductName = <商品名> });| View(); methodは、Viewを指定しないoverloadで呼び出すと、 /Views/コントローラ名/アクション名.cshtml を呼び出す。 上記以外にも、 -ファイルダウンロード用の FileResult -JavaScript 実行用の JavaScriptResult などがある。 詳しくは [[ActionResult クラス>https://msdn.microsoft.com/ja-jp/library/system.web.mvc.actionresult.aspx]]を参照。 **画面遷移の方法 [#ycae9af6] [[モジュール化の要約>#j2c8410a]]で紹介した、[[スキャフォールディング方式>#td62a820]]、[[View ごとに Controller を作成する方式>#se3008cd]]ともに、リクエストの処理フローは以下のようになる。 +View から、対応する Controller にリクエストを送る~ (書こうと思えば、任意の Controller にリクエストを送ることはできるが、View と Controller の関係が複雑になるのでオススメしない) +Controller はリクエストを受け付け、Model に処理を指示する +Model は業務ロジックを実行し、データを更新する +Controller は View に表示を指示する ここで、''どの View に表示の指示をするか''によって、使用する ActionResult クラスが変わる。 -その Controller に対応する View に、表示を指示する場合 --ViewResult を使用する -別の Controller に対応する View に、表示を指示する場合 --RedirectToActionResult または RedirectToRouteResult を使用する *フォルダ構成 [#c0d7785c] ASP.NET MVC のテンプレートには、グルーピングを目的に、既定で以下のフォルダ構成となっている。~ それぞれのフォルダには、以下のようにファイルを配置することが推奨されている。 |フォルダ名|配置されるファイル|備考|h |App_Start|起動時に、初期設定を行うモジュール|-| |Contents|CSS|BundleConfig が使用しているため、既定の CSS ファイルは変更しない| |Controllers|Controller|-| |Models|Model|-| |Scripts|JavaScript|BundleConfig が使用しているため、既定の JavaScript ファイルは変更しない| |Views|View|対応する Controller 名のフォルダ以下に、View のファイルを配置する&br();例&br();Views&br(); -(コントローラー名)&br(); -Index.cshtml| ***Area [#re760150] Area (区分) とは、ASP.NET MVC アプリケーションを論理的に分割する仕組みのことである。~ (ASP.NET MVC プロジェクトをシステム全体とすると、Area ごとにサブシステム (のようなもの) に分割できる。~ App_Start のマップルートが追加されるような感じ、と理解すると分かりやすいかもしれない) *情報の持ち回り・状態管理方式 [#i6db0cb0] -ViewState~ 利用不可能 (必要であれば、自前で ViewState に相当するものする必要がある) -Hidden~ 使用可能 -Session~ 使用可能 *チェック処理方式 [#hc015ceb] **クライアント [#i39f251f] JavaScript でのチェック。~ [[jQuery Validation プラグイン>https://jqueryvalidation.org/]]なども使用可能。 **サーバ [#k1290bb8] Action メソッド内でのチェック。~ 個別にチェックロジックを実装するか、アノテーションを使用したチェックが可能。 -お楽しみはこれからだ! --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が必要)。 --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 *脆弱性 [#jd31de6d] **サニタイジング [#m59baf7f] -HTML ヘルパーを使用すると、自動的にサニタイジングが行われる。 -Model のプロパティを直接 View に表示する場合は、自前でのサニタイジングが必要。 **リクエスト検証 [#ra245005] -requestValidationMode を MVC でも利用可能。~ http://stackoverflow.com/questions/6206540/what-does-requestvalidationmode-2-0-actually-do ---- タグ: [[:ASP.NET MVC]]