モデルを表示するのは比較的新しいので、モデルの使用に関していくつかの問題が発生しています。これが、ベストプラクティスとは何か疑問に思っている状況の1つです...
ビューに必要なすべての情報をビューモデルに入れています。ここに例があります-エラーを許してください、これは私の頭のてっぺんからコード化されています。
public ActionResult Edit(int id)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
var model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
return View(model);
}
画面で1つまたは2つのフィールドの編集しか許可されていない場合、ビューモデルが戻ってきたときに、かなりの量のデータが失われています(本来あるべきことです)。
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
try
{
if (!ModelState.IsValid)
return View(model) // Won't work, view model is incomplete.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // Won't work, view model is incomplete.
}
}
私の一時的な解決策は、ビューモデルを最初から再作成し、ドメインモデルから再入力し、フォームデータを再適用してから、通常どおりに続行することです。しかし、これはビューモデルパラメータをやや無意味にします。
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
// Recreate the view model from scratch.
model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
try
{
TryUpdateModel(model); // Reapply the form data.
if (!ModelState.IsValid)
return View(model) // View model is complete this time.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // View model is complete this time.
}
}
もっとエレガントな方法はありますか?
[〜#〜]編集[〜#〜]
どちらの答えも正しいので、できれば両方を授与します。しかし、試行錯誤の末、彼の解決策が最も無駄がないことがわかったので、うなずきはMJに行きます。
私もヘルパーを使うことができます、ジミー。表示する必要があるものをビューバッグ(またはビューデータ)に追加すると、次のようになります...
ViewBag.Project= project;
その後、次のことができます...
@Html.LabelFor(model => ((Project)ViewData["Project"]).Name)
@Html.DisplayFor(model => ((Project)ViewData["Project"]).Name)
ちょっとしたハックで、ドメインモデルをSystem.ComponentModel.DisplayNameAttribute
で装飾する必要がある場合もありますが、私はすでにそうしています。
電話したい...
@Html.LabelFor(model => ViewBag.Project.Name)
しかし、動的は式に問題を引き起こします。
試行錯誤(コード化してから嫌い)を学んだ後、現在私が好むアプローチは次のとおりです。
View-models onlyを使用して入力フィールドをバインドします。したがって、あなたの場合、ビューが2つのフィールドのみを編集している場合、ビューモデルには2つのプロパティしかありません。ビューにデータを入力するために必要なデータ(ドロップダウンリスト、ラベルなど)には、動的なViewBagを使用します。
ビューを表示すること(つまり、ビューに表示する必要があるものをすべて入力すること)と、投稿されたフォーム値をキャプチャすること(バインド、検証など)は、2つの別個の関心事であると私は信じています。また、ビューにデータを入力するために必要なデータと、ビューからポストバックされたデータを混在させると、煩雑になり、状況が正確に作成されることがよくあります。部分的に実装されたオブジェクトが渡されるのは嫌いです。
Automapper(ドメインオブジェクトを動的ViewBagにマッピングするため)でこれがどのように機能するかはわかりませんが、使用したことがありません。動作する可能性のあるDynamicMapメソッドがあると思いますか?投稿された強く型付けされたViewModelをDomainオブジェクトに自動マッピングすることに問題はありません。
私が正しく理解していれば、ビューモデルはおそらくドメインエンティティに非常によく似ています。特定のフィールドのみが編集可能であるため、ビューモデルはほとんど空に戻る可能性があるとおっしゃいました。
編集(または表示)できるフィールドが少ないビューがあるとすると、これらはビューモデルで使用できるようにする必要があるonlyフィールドです。私は通常、ビューごとに1つのビューモデルを作成し、コントローラーまたはサービスのいずれかがユーザーの入力を処理し、検証を実行した後、ドメインエンティティにマップし直します。
ここ は、役立つと思われるビューモデルのベストプラクティスに関するスレッドです。
編集:編集/ POSTアクションで編集/ GETアクションが提供するものとは異なるビューモデルを受け入れることもできます。モデルバインダーがそれを理解できる限り、これは機能するはずだと思います。