よし、ようやく正しい方法だと思われる実用的なコードがいくつかできました。これが私が行ったものです。2 つの単純な「エンティティ」があります。顧客と BillingCustomer。それらは実際には別々の「境界付けられたコンテキスト」にあることを意図しており、クラスはデモストレーションの目的のために非常に単純です。
public class Customer
{
public Guid CustomerId { get; set; }
public string Name { get; set; }
}
public class BillingCustomer
{
public Guid CustomerId { get; set; }
public bool IsOverdueForPayment { get; set; }
}
両方のクラスが CustomerId を参照していることに注意してください。このデモでは、これは GUID です。
まず、Index.cshtml ファイルで使用される ViewModel を構築する単純な HomeController から始めました。
public ActionResult Index()
{
var customer = new Customer {
CustomerId = Guid.Empty,
Name = "Mike McCarthy" };
var billingCustomer = new BillingCustomer {
CustomerId = Guid.Empty,
IsOverdueForPayment = true };
var compositeViewModel = new CompositeViewModel {
Customer = customer,
BillingCustomer = billingCustomer };
return View(compositeViewModel);
}
CompositeViewModel クラスは、各ドメイン エンティティのプロパティを持つ単なる DTO です。これは、Index.cshtml ファイルで呼び出す部分ビューが、それぞれのドメイン モデルを部分ビューに渡す必要があるためです。
public class CompositeViewModel
{
public BillingCustomer BillingCustomer { get; set; }
public Customer Customer { get; set; }
}
HomeController で Index メソッドを使用する結果の Index.cshtml ファイルを次に示します。
@model CompositeViews.ViewModels.CompositeViewModel
<h2>Index - @DateTime.Now.ToString()</h2>
<div id="customerDiv">
@{Html.RenderPartial("_Customer", Model.Customer);}
</div>
<p></p>
<div id="billingCustomerDiv">
@Html.Partial("_BillingCustomer", Model.BillingCustomer)
</div>
ここで注意すべき点がいくつかあります。
- ビューは CompositeViews.ViewModels.CompositeViewModel ViewModel を使用しています
- Html.RenderPartial は、各エンティティの部分ビューをレンダリングするために使用され、適切なエンティティを渡します。Html.Partial 呼び出しの構文に注意してください。
したがって、ここに _Customer 部分ビューがあります。
@model CompositeViews.Models.Customer
@using (Ajax.BeginForm("Edit", "Customer", new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "customerDiv" }))
{
<fieldset>
<legend>Customer</legend>
@Html.HiddenFor(model => model.CustomerId)
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
ここで重要な部分は、Ajax.BeginForm 呼び出しです。CustomerController の Edit ActionMethod を明示的に呼び出していることに注意してください。また、UpdateTargetId が「customerDiv」に設定されていることにも注意してください。この div は部分ビューではなく、"親" ビューの Index.cshtml にあります。
以下は _BillingCustomer ビューです
@model CompositeViews.Models.BillingCustomer
@using (Ajax.BeginForm("Edit", "BillingCustomer", new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "billingCustomerDiv" }))
{
<fieldset>
<legend>BillingCustomer</legend>
@Html.HiddenFor(model => model.CustomerId)
<div class="editor-label">
@Html.LabelFor(model => model.IsOverdueForPayment)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.IsOverdueForPayment)
@Html.ValidationMessageFor(model => model.IsOverdueForPayment)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
ここでも、UpdateTargetId がbillingCustomerDiv に設定されていることに注意してください。この div は、この部分ビュー ファイルではなく、Index.cshtml ファイルにあります。
したがって、まだ見ていないのは、CustomerController と BillingCustomerController の Edit ActionResult だけです。ここにカスタマーコントローラーがあります
public class CustomerController : Controller
{
[HttpGet]
public PartialViewResult Edit(Guid customerId)
{
var model = new Customer {
CustomerId = Guid.Empty,
Name = "Mike McCarthy"};
return PartialView("_Customer", model);
}
[HttpPost]
public ActionResult Edit(Customer customer)
{
return PartialView("_Customer", customer);
}
}
この投稿では複合 UI の構築を直接扱っているため、このコントローラーでは実際に「起こっている」ことは何もありません。「PartialView」を介して戻り、使用する部分ビューの名前と、ビューがレンダリングする必要がある必要なモデルを指定する方法に注目してください。
これが BillingCustomerController です
public class BillingCustomerController : Controller
{
[HttpGet]
public PartialViewResult Edit(Guid customerId)
{
var model = new BillingCustomer {
CustomerId = Guid.Empty,
IsOverdueForPayment = true };
return PartialView("_BillingCustomer", model);
}
[HttpPost]
public PartialViewResult Edit(BillingCustomer billingCustomer)
{
return PartialView("_BillingCustomer", billingCustomer);
}
}
ここでも CustomerController と同じですが、このコントローラーが BillingCustomer エンティティを処理しているという点が異なります。
HomeController の Index ActionResult をロードすると、次のような画面が表示されます。
各 [保存] ボタンは、ページ全体の通常のポストバックを発生させることなく、部分ビューがデータを取得するために更新して対話する必要があるコントローラーへの非同期ポストバックを実行します。どちらの保存ボタンを押しても、DateTime スタンプが変更されないことがわかります。
これが、部分ビューを使用して最初の複合ビューを構築する方法でした。私はまだMVC3に非常に慣れていないので、何かを台無しにしたり、必要以上に難しい方法で何かをしたりする可能性がありますが、これが私がそれを機能させた方法です.