[解決済み] MVCにおけるViewModelとは?
質問
ASP.NET MVCの初心者です。ViewModelの目的を理解するのに問題があります。
ViewModel とは何ですか?また、なぜ ASP.NET MVC アプリケーションに ViewModel が必要なのでしょうか?
その動作と説明について良い例があれば、より良いのですが。
解決方法は?
A
view model
は、ビュー/ページに表示するデータを表します。静的なテキストとして使用するか、データベースに追加 (または編集) できる入力値 (テキストボックスやドロップダウンリストなど) として使用するかは問いません。これは
domain model
. これは、ビューのモデルです。
があるとします。
Employee
クラスは従業員ドメインモデルを表し、次のプロパティ (一意な識別子、姓、名、および作成日) を含んでいます。
public class Employee : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateCreated { get; set; }
}
ビューモデルはドメインモデルとは異なり、ビュー上で使用したいデータ(プロパティで表される)だけを含むモデルです。 例えば、新しい従業員レコードを追加したいとすると、ビューモデルは次のようになります。
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
見てわかるように、これには2つのプロパティしか含まれていません。この2つのプロパティは、従業員ドメイン・モデルにも含まれています。 これはなぜか、と聞かれるかもしれません。
Id
はビューから設定されるのではなく、Employeeテーブルによって自動生成される可能性があります。 また
DateCreated
は、ストアドプロシージャやアプリケーションのサービスレイヤーで設定されるかもしれません。 そのため
Id
と
DateCreated
はビューモデルでは必要ありません。従業員の詳細(すでに捕捉されている従業員)を表示する際に、この2つのプロパティを静的テキストとして表示したい場合があります。
ビュー/ページを読み込む際に、従業員コントローラの create アクションメソッドはこのビューモデルのインスタンスを作成し、 必要に応じてフィールドに情報を入力し、 このビューモデルをビュー/ページに渡します。
public class EmployeeController : Controller
{
private readonly IEmployeeService employeeService;
public EmployeeController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
public ActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
return View(model);
}
public ActionResult Create(CreateEmployeeViewModel model)
{
// Do what ever needs to be done before adding the employee to the database
}
}
ビュー/ページは次のようになります。
ASP.NET MVC
であり
Razor
ビューエンジン)。
@model MyProject.Web.ViewModels.CreateEmployeeViewModel
<table>
<tr>
<td><b>First Name:</b></td>
<td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
@Html.ValidationMessageFor(m => m.FirstName)
</td>
</tr>
<tr>
<td><b>Last Name:</b></td>
<td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
@Html.ValidationMessageFor(m => m.LastName)
</td>
</tr>
</table>
このように、バリデーションは
FirstName
と
LastName
. 使用方法
FluentValidation(フルエントバリデーション
のようなバリデーションを行うことができます。
public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
public CreateEmployeeViewModelValidator()
{
RuleFor(m => m.FirstName)
.NotEmpty()
.WithMessage("First name required")
.Length(1, 50)
.WithMessage("First name must not be greater than 50 characters");
RuleFor(m => m.LastName)
.NotEmpty()
.WithMessage("Last name required")
.Length(1, 50)
.WithMessage("Last name must not be greater than 50 characters");
}
}
そして、Data Annotationsを使用すると、次のようになります。
public class CreateEmployeeViewModel : ViewModelBase
{
[Display(Name = "First Name")]
[Required(ErrorMessage = "First name required")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Last name required")]
public string LastName { get; set; }
}
覚えておくべき重要なことは、ビューモデルは、あなたが使いたいデータのみを表すということです それ以外には何もありません。 もし、30個のプロパティを持つドメインモデルがあって、1つの値だけを更新したい場合、すべての不要なコードと検証を想像することができます。 このシナリオでは、ドメインオブジェクトにあるすべてのプロパティではなく、ビューモデルにあるこの1つの値/プロパティのみを持つことになります。
ビューモデルは、1つのデータベース・テーブルからのデータだけを持つとは限りません。別のテーブルのデータを組み合わせることもできます。新しい従業員レコードを追加することについて、上記の私の例を見てください。姓と名を追加するだけでなく、その従業員の部署を追加したいかもしれません。この部門のリストは、あなたの
Departments
テーブルを使用します。これで
Employees
と
Departments
テーブルを1つのビューモデルに統合します。あとは、以下の2つのプロパティをビューモデルに追加して、データを投入するだけです。
public int DepartmentId { get; set; }
public IEnumerable<Department> Departments { get; set; }
従業員データ(すでにデータベースに追加されている従業員)を編集する場合は、上記の例とあまり変わりません。 ビューモデルを作成し、それを例えば
EditEmployeeViewModel
. このビューモデルには、姓や名のような編集したいデータだけを入れておきます。データを編集して、送信ボタンをクリックします。私なら、あまり気にせず
Id
フィールドは
Id
の値は、おそらく URL などに含まれていることでしょう。
http://www.yourwebsite.com/Employee/Edit/3
これを持って
Id
を作成し、姓と名の値とともにリポジトリレイヤーに渡します。
レコードを削除する場合、私は通常、編集ビューモデルと同じ経路をたどります。また、例えばURLも用意します。
http://www.yourwebsite.com/Employee/Delete/3
ビューが初めてロードされたとき、私は、データベースから
Id
その後、削除される従業員がわかるように、ビュー/ページに静的テキストを表示します。ユーザーが削除ボタンをクリックすると、私は単に
Id
の値を3にして、リポジトリレイヤーに渡します。必要なのは
Id
を使用してテーブルからレコードを削除します。
もう一点、すべてのアクションにビューモデルが必要なわけではありません。単純なデータなら
EmployeeViewModel
. もし、複雑なビューやページがあり、それらが互いに異なる場合は、それぞれに別のビューモデルを使用することをお勧めします。
これで、ビューモデルとドメインモデルについて持っていた混乱が解消されれば幸いです。
関連
-
[解決済み] Could not find a part of the path ... binroslyncsc.exe
-
[解決済み] データベースに 'AspNetRoles' という名前のオブジェクトがすでに存在します。
-
[解決済み] ASP.NET MVC - カスタムIIdentityまたはIPrincipalの設定
-
[解決済み] ELMAHをASP.NET MVCの[HandleError]属性で動作させる方法は?
-
[解決済み] 修正方法: ハンドラ "PageHandlerFactory-Integrated" のモジュールリストに "ManagedPipelineHandler" という不正なモジュールが含まれています。
-
[解決済み] IIS7 の「クラシック」パイプラインモードと「統合」パイプラインモードの違いは何ですか?
-
[解決済み] ASP.NET MVCのビューを文字列としてレンダリングする方法は?
-
[解決済み] ASP.NET MVCにおけるApiControllerとControllerの相違点
-
[解決済み】ASP.NET MVCでクライアントのIPアドレスを取得するにはどうすればいいですか?
-
[解決済み】ViewModelのベストプラクティス
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】同じキーのアイテムがすでに追加されています。
-
[解決済み] Razor View throwing "The name 'model' does not exist in the current context".
-
[解決済み] MVCにおけるViewModelとは?
-
[解決済み] ASP.NET MVCでHTML-5のdata-*属性でダッシュを使用する方法
-
[解決済み】ASP.NET MVC 3 Razor - EditorForにクラスを追加する。
-
[解決済み] [Solved] ASP.NET MVCコントローラメソッドからJSON.NETでシリアライズされたcamelCase JSONを返すにはどうすればよいですか?
-
[解決済み】AutoMapper.CreateMapsをどこに配置するか?
-
[解決済み] ASP.NET MVCにおけるロールベースアクセスコントロール(RBAC)とクレームベースアクセスコントロール(CBAC)の比較
-
[解決済み] MVCとRazorにおけるHtml.TextboxForとHtml.EditorForの相違点
-
[解決済み] ASP.NET MVCのモデルでUrlHelperを呼び出す