マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

ASP.NET MVCの利用方法」は
ASP.NET MVCの用語」と比べて、
少々高度な応用的トピックをまとめています。

モジュール化の考え方

M・V・Cの役割の整理

まず、Model と View と Controller の役割について整理する。

  • Model:
    • アプリケーションの基礎となるデータ構造(ViewModel?)、
    • およびそのデータを取得・加工する業務ロジック
  • View:
    Model が保持するデータ(ViewModel?)を参照し、ユーザーに表示する。
  • Controller:
    • ユーザーからの入力を受け取り、
    • Model に対してデータの取得・加工を指示する。
    • その結果を受けて、View に表示を指示する。

画面 or データモデル、どちらをベースにするか?

ASP.NET MVCの開発は、ViewModel?ModelMetadata?駆動になる。

このため、ViewModel?の設計が重要になるが、これを

  • 画面をベースにするか?
  • データモデルをベースにするか?

どちらをベースにするか?でモジュール化が異なってくる。

Modelと全体Viewの関係

Model (0..1) <---> (1) 全体View

Model (0) <---> (1) 全体View

全体View が、Model が保持するデータを何も表示しない状態。(静的なページなど?)

Model (1) <---> (1) 全体View

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

Controllerと全体Viewの関係

全体View (1..*) <---> (1) Controller

全体View (1) <---> (1) Controller

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

複数の 全体View に対して、1 つの Controller を対応させる考え方。

アプリケーションの

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

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

スキャフォールディング(scaffolding)方式

たとえば、受注処理を行うアプリケーションを考えると、
「受注作成画面」・「受注内容更新画面」・「受注削除画面」など、
複数の 全体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

モジュール化の要約

Controllerをどのような単位で作成するかにかかっている。

機能やデータ構造に対して 1 つの Controller を対応させる方式

  • 全体View (1..*) <---> (1) Model
  • Controller (1) <---> (1..*) Model
  • 全体View (1..*) <---> (1) Controller

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

  • 全体View (1..*) <---> (1) Model
  • Controller (1) <---> (1..*) Model
  • 全体View (1) <---> (1) Controller

Controller の作成

モジュール化

モジュール化の要約で紹介した、

何れかの方針に合わせて、Controllerを作成する。

利用可能な属性

HTTP メソッド属性

特定の HTTP メソッドのみを受け入れる属性を付与することができる。

なお、Action MethodにHTTPメソッド属性を指定しなかった場合、
Action Methodは、すべての HTTP メソッドを受け入れる。

AcceptVerbs? 属性は、複数のHTTPメソッドを受け入れるAction Methodの定義に使用する。

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

  • [HttpGet?] メソッド属性
    • 概要
      • Get メソッドのみ受け入れる。
      • それ以外の HTTP メソッドは受け入れない(404 が返る)。
    • ユースケース
      • Get で別画面に画面遷移する場合
      • 入力項目が無い状態で、同一画面内で状態遷移する場合
  • [HttpPost?] メソッド属性
    • 概要
      • Post メソッドのみ受け入れる。
      • それ以外の HTTP メソッドは受け入れない(404 が返る)。
    • ユースケース
      • フォームの入力項目を Controller に Post する場合。
      • Post で別画面に画面遷移する場合。
  • , etc.

ActionName?属性

Action Method名と、外部に公開するAction Nameとを別にする。

例えば

項番Action Method名ActionName?処理の内容
DeleteDelete削除画面の初期表示処理
DeleteConfirmed?Delete削除処理の実行

ValidateAntiForgeryToken?属性

CSRF対策に使用する。
複数ブラウザウィンドウ対応がなされているかどうかは未確認。

  • View
    @using (Html.BeginForm())
    {
        @* トークンを埋め込む *@
        @Html.AntiForgeryToken()
    }
  • Controller
    // トークンを検証する
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed()
    {
        ・・・
    }

Model の作成

モジュール化

モジュール化の考え方のように、Model には 2 つの意味がある。

  • アプリケーションの基礎となるデータ構造
    • POCO として作成する。
    • XXXXViewModel?という名称を付与する。
  • そのデータを取得・加工する業務ロジック
    • 通常の業務ロジック・クラスとして作成する。

ココでは前者について言及する。

利用可能な属性

System.ComponentModel?.DataAnnotations?属性により、

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

DataType?属性

型情報を指定することで、

として使用される。

[DataType(DataType.XXXX)]
  • 参考

DataType?の派生の属性

DataType属性と同様に利用される。

  • 参考

DisplayName?, Display属性

表示名(Label表示を行なうHtmlヘルパーに使用される)

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

DisplayFormat?属性

フォーマットの指定。

[DisplayFormat(DataFormatXXXX="YYYY")]

UIHint属性

  • 独自の表示/編集テンプレート・ヘルパーを準備する。
  • 例えばDateTime?型を指定したEditorFor?
    使用するjQuery UIのDatepickerを適用する。

DisplayColumn?属性

検証属性

検証属性については、コチラ

ViewModel?の作成方法

ASP.NET MVCでDataTableを使用する。

AutoMapperを使用する。

View の作成

モジュール化

Razer、ASPX の使い分け

基本、Razer(主流)を使用する。

BeginForm? の使い分け

ASP.NET MVC には、<form> タグを生成する Htmlヘルパーが 2 種類ある。
BeginForm? ヘルパーは引数にコントローラー名、アクション名が付与でき、指定したアクションメソッドにリクエストを送ることができる。

HTML.BeginForm?

通常の <form> タグを生成する場合に使用する。

  • 全体更新が多数を占める場合 (アクションメソッドの結果として、View 全体を更新する場合)。
  • 画面リフレッシュにより、リクエスト・レスポンスのステータスを明確にしたい場合。

Ajax.BeginForm?

<form> タグに Ajax リクエスト用の属性が付与され、リクエストが非同期で処理される。

  • 部分更新が多数を占める場合 (アクションメソッドの結果として、View の一部分のみを更新する場合)。
  • サーバー側処理が非常に重い業務の場合 (Ajax は非同期処理のため)。
  • 画面入力状態を保持したまま POST 送信したい場合
    • ViewStateがサポートされない MVC で、情報復元処理を割愛したい場合。
  • リクエスト・レスポンスのサイズを削減して、性能向上を図りたい場合。
  • 画面リフレッシュによる、画面のちらつきなどをなくしたい場合。

参考

From タグの切り方

画面設計によるが、以下を考慮する。

  • 1 View に対して 1 Form?
  • 1 View に対して複数 Form?

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

Htmlヘルパーの使い分け

Htmlヘルパー(Html.xxxx と Html.xxxxFor

  • Html.xxxxFor
    • ポスト時にModelデータを復元する場合。
    • 例えばエラー発生時に、自画面の再表示(≒ポストバック)をする場合。
  • Html.xxxx
    上記以外は、Html.xxxxで良い。

GridView?的な一覧(グリッド)生成用のHtmlヘルパー

ASP.NET MVC で一覧(グリッド)のある View を作成する場合、以下の 3 種類が考えられる。

  • WebGrid クラスを使用する
    ソートやページングが容易に実装できる反面、レンダリング部分は多少ブラックボックスになる
  • <table> タグを自前で生成し、<tr> タグをループで実装する
    ASP.NET の Repeater コントロールのような処理の実装方法(Razorなぶん楽)。
  • jqGrid など、OSS の JavaScript ライブラリを使用する。

テンプレート・ヘルパー(テンプレートに対応したHtmlヘルパー)

DisplayFor?EditorFor?などモデル定義に応じて出力を自在に変えられるHtmlヘルパー。

  • Htmlヘルパー
    • DisplayFor?DisplayForModel?:データの表示
      • DisplayFor?
      • DisplayForModel?:Model単位にテンプレート・ヘルパーを決定する。
  • EditFor?EditForModel?:データ編集項目の生成
    • EditFor?: Htmlヘルパーの第二引数でテンプレート・ヘルパーを指定できる。
      UIHint属性で指定したテンプレート・ヘルパーが使用される。
      属性の優先度は、UIHint属性 -> DataType?属性 -> 実際のデータ型
    • EditForModel?:Model単位にテンプレート・ヘルパーを決定する。
  • テンプレート・ヘルパー名とテンプレート・ヘルパー配置場所
    • 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

Html.Hidden または Html.HiddenFor?

タイムスタンプ型など、ユーザに見えない情報だが
内部処理に必要な情報を引き継ぐ場合に使用する。

カスタムHtmlヘルパー(カスタム・コントロールみたいな)

画面遷移

モジュール化の要約で紹介した、

共に、画面遷移の処理フローは以下のようになる。

処理フロー

  1. View から、対応する Controller にリクエストを送る
  2. Controller はリクエストを受け付け、Model に処理を指示する
  3. Model は業務ロジックを実行し、データを更新する
  4. Controller は View に表示を指示する

実装方法

なお、1つの View が、任意の Controller にPOSTリクエストを送る
ASP.NET Web Formsの「ページ間ポスティング」的な実装も書けるが、
View と Controller の関係が複雑になるのでオススメしない。

従って、上記の「4.」で、どの View に表示の指示をするかによって、
使用する ActionResult? クラスを下記のように変える様に実装する。

  • その Controller に対応する View に、表示を指示する場合
    • ViewResult? を使用する
  • 別の Controller に対応する View に、表示を指示する場合
    • RedirectToActionResult? または RedirectToRouteResult? を使用する

モバイル対応

Mobil Template

「モバイル アプリケーション」テンプレートを使用して、
モバイルデバイス向けアプリケーションを作成できる。
このテンプレートでは、jQuery Mobile をベースとしており、
タッチ操作に最適化した UI を構築できる。

DisplayModes?

Bootstrapによるレスポンシブデザインに頼らず、
PC 向けサイト、モバイル向けサイトの画面を分けるアプローチ。

  • DesktopかMobilかは、UserAgent?UserHostAddress?を使用して判別している。
  • 通常、XXXXX.cshtmlとXXXXX.Mobil.cshtmlの2つのViewスクリプトを作成する。
    上記は、マスタページや部分ViewなどのViewスクリプトにも適用することができる。
    • XXXXX.cshtml (PC 向けサイト)
    • XXXXX.Mobil.cshtml (モバイル向けサイト)
  • 以下のコードを追加してデバイスごとに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)
          });
      }

この時、

  • 「XXXXX.cshtml」と同じフォルダに
  • 「XXXXX.iPhone.cshtml」を作成し、

iPhone 向けのレイアウトを定義すると、

http://server/application/Controller/Index/id

という同じ URL に対し、

  • PC のブラウザからアクセスした場合、「Index.cshtml」が使用され、
  • iPhone からアクセスした場合は「Index.iPhone.cshtml」が使用されるようになる。

その他

WebViewPage?

このクラスで設定・追加したプロパティが、
各Viewファイル(.cshtmlや.vbhtml)の開発時に使用出来るようになる。

情報の持ち回り・状態管理方式

ViewState

利用不可能

  • 必要であれば、ViewState相当の状態保存処理を独自実装する必要がある。

Hidden

使用可能

Session

使用可能

検証機能

Action メソッド内で個別にチェックロジックを実装するか、
ModelMetadata?を使用したチェックが可能。

Model側

検証属性

以下の属性を使用して検証可能。

項番属性概要
DataType属性(enumDataType?, errmsg)指定のデータ型に変換可能か
Required属性(errmsg)必須入力
StringLength?属性(max, errmsg)文字列の最大長
MaxLength?属性(max, errmsg)文字列の最大長
MinLength?属性(min, errmsg)文字列の最小長
Range属性(min, max, errmsg)範囲
RegularExpression?属性(pattern, errmsg)正規表現
MembershipPassword?属性()パスワード
Compare属性(targetname, errmsg)比較(e-mailやpasswdの確認用フィールドに使用する)
10Remote属性(actionMethod, errmsg)Ajaxを使用したチェック
11CustomValidation?属性()カスタム

各属性の errmsgプロパティに何も設定しなくても既定でエラーメッセージが出る。

DataType属性

DataType属性検証属性として機能する。

  • 参考

CustomValidation?属性

ざっくり、以下のようにして、CustomValidation?属性を使用する。

  • 単項目チェック処理
    • プロパティにCustomValidation?属性を設定し、呼び出す検証メソッドと関連付ける。
    • CustomValidation?属性に設定した、staticの検証メソッドを定義する。
    • 検証メソッドでは、検証結果として、ValidationResult?を返す。
  • 関連チェック処理
    • モデルにCustomValidation?属性を設定し、呼び出す検証メソッドと関連付ける。
    • CustomValidation?属性に設定した、staticの検証メソッドを定義する。
    • 検証メソッドでは、検証結果として、ValidationResult?を返す。

自作Validation属性

ざっくり、以下のようにして、自作Validation属性を定義して使用する。

  • 単項目チェック処理
    • プロパティに自作Validation属性を指定して検証パラメタやエラーメッセージを指定する。
  • 自作Validation属性の作成
    • ValidationAttribute?クラスを継承した自作Validationを定義する。
  • コンストラクタを実装
    検証パラメタとエラーメッセージを準備(必要に応じてパラメタライズ)
  • メソッドをoverrideして実装する。
    • FormatErrorMessage?メソッドでエラーメッセージを生成
    • IsValid?メソッドで検証処理を実装し、検証結果として、boolを返す。
  • 自作Validation属性をクライアント側検証に対応させる。
  • IClientValidation?インターフェイスを実装する。
    • 属性とViewの橋渡しを行なうGetClientValidationRule?メソッドを実装する。
    • GetClientValidationRule?メソッドでは、IEnumerable<ModelClientValidationRule?>を返す。
    • これにより、検証名に対応する検証パラメタとエラーメッセージがHTML側に属性として出力される。
  • jQuery Validation プラグインとの関連付け。
    検証ロジックとを独自jsファイルに定義する。
    • $.Validator.addMethod('検証名'~、
    • $.validator.unobtrusive.adapters.addSingleVal?('検証名', '検証パラメタのKey');。
    • BundleConfig?.csに、この独自jsファイルをjqueryvalにincludeするバンドル定義を追加する。

IValidatableObject?の実装

ざっくり、以下のようにして、IValidatableObject?を使用する。
複数の検証結果を返せるのは、IValidatableObject?だけである。

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

Controller側

検証タイミング

Action Methodの実行前に、モデル・バインディングが行われたタイミング。

ModelStateDictionary?

  • 概要
    • Controller.ModelState?でアクセスできる。
    • モデルの状態とモデル・バインディングの検証結果を含む。
  • Property
    • IsValid? プロパティ
      モデル・バインディングの検証結果として、モデルの有効・無効を返す。
    • Keysプロパティ
    • Valuesプロパティ
  • Method
    • ModelState?.AddModelError?()
      エラー情報を追加する。

View側

サーバ側

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

クライアント

  • 検証後に適用される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
      検証エラーが発生した要素

appSettings

クライアント側検証の無効化

CustomValidation属性ではクライアント側検証が実行されない。
整合性をとるために、クライアント側検証の無効化を行なう。

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

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

控えめなJavaScript

クライアント側検証に「控えめなJavaScript」のパラダイムが導入されている。

  • *.htmlファイル側にJavaScriptではなく、属性を書く。
  • JavaScriptは*.jsファイル側に書いて、HTMLとJavaScriptを分離する。
  • 「控えめなJavaScript」は以下のパラメタで制御できる。
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

参考

スキャフォールディング

概要

スキャフォールディング(Scaffolding)。
日本語で「足場」、「骨組み」の意味。

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

を自動で生成する機能。

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

M(Model)

  • 使用するModelを選択する。
  • Modelの新規作成も可能

設定する属性

ナビゲーション・プロパティ

C(Controller)

  • M(Model)の複数形 + Controllerという名称になる。
  • Action Method
    • Index
    • Details
    • Create
    • Edit
    • Delete

V(View)

  • Entity Frameworkを使用すると、以下のようにViewまで自動生成される。
  • また、Entity Frameworkを使用しない場合も、個別に、
    ModelMetadata?を定義したModelを指定しView追加(スキャフォールディング)ができる。
項番View名対応するAction Method名使用されるTemplate名
1Index.cshtmlIndexList
2Details.cshtmlDetailsDetails
3Create.cshtmlCreateCreate
4Edit.cshtmlEditEdit
5Delete.cshtmlDeleteDelete

テンプレートをオーバーライド

ModelMetadata?を使用した開発

検証機能

スキャフォールディング

脆弱性

サニタイジング

  • Htmlヘルパーを使用すると、自動的にサニタイジングが行われる。
  • Model のプロパティを直接 View に表示する場合は、自前でのサニタイジングが必要。

リクエスト検証

認証

ASP.NET MVCのテンプレートでは、

ASP.NET Forms認証

ASP.NET Identity

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

その他

Entity Framework

ASP.NET Web API

ASP.NET SPA


Tags: :.NET開発, :ASP.NET, :ASP.NET MVC


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-09-06 (木) 10:08:11 (14d)