ASP.NET MVC 3.0知識メモ(3)【主従属性共同編集後のフォーム提出】

17946 ワード

一般的に、あるエンティティを編集するのは問題ありません.例えば、マイクロソフトの公式音楽ショップでは、自動的に生成されたコードでスムーズにできます.しかし、2つのモデルを一緒に編集し、Actionに一緒に提出するビジネスシナリオがあり、問題が発生しました.たとえば、受注や受注明細などです.
一.使用する実装クラスを列挙
/// <summary>
///
/// </summary>
public class Order
{
public int OrderID { set; get; }

[Display(Name = " ")]
public string Description { set; get; }

[Display(Name = " ")]
public string CreatePerson { set; get; }

[Display(Name = " ")]
public DateTime CreateDate { set; get; }

[Display(Name=" ")]
public int CategoryID { set; get; }
public List<OrderDetail> OrderDetailList { set; get; }
}

/// <summary>
///
/// </summary>
public class OrderDetail
{
public int OrderDetailID { set; get; }
public int OrderID { set; get; }
public string ProductName { set; get; }
public int Amount { set; get; }
public double UnitPrice { set; get; }
}

/// <summary>
///
/// </summary>
public class Category
{
public int CategoryID { set; get; }
public string CategoryName { set; get; }
}

赤い線を太くしたエンティティは、次にマスターがエンティティから同時に編集し、同時に提出するマスター解です.
 
二.2つのアクションを定義します.1つはページを開くために使用され、1つはクライアントがフォームを発行する要求に応答するために使用されます.
  • Get要求に基づくCreateOrder()はページを表示するために使用され、Viewビューレイヤを介して注文本体Orderを表示し、注文スレーブOrderDetail(Ajax非同期ロードに基づいて生成)を表示する前に、注文タイプドロップダウンボックスを初期化します.SelectListクラス:
  • が必要です.
    [HttpGet]
    public ActionResult CreateOrder()
    {
    var CategoryItems = new List<Category>() {
    new Category(){
    CategoryID = 10,
    CategoryName = " "
    },
    new Category(){
    CategoryID = 11,
    CategoryName = " "
    }
    };

    ViewData["Order.CategoryID"] = new SelectList(CategoryItems, "CategoryID", "CategoryName", "");

    return View();
    }
  • クライアントがフォームを送信する要求に応答するために使用される:
  • [HttpPost]
    public ActionResult CreateOrder(Order order)
    {
    order.OrderDetailList = orderDetails;
    return RedirectToAction("CreateOrder");
    }

     
    三.従属モデルをPartialViewにする
    @model TelerikMvcApplication1.Models.OrderDetail
    @using TelerikMvcApplication1.Helpers

    <div class="editorRow">
    @using (Html.BeginCollectionItem("Order.OrderDetailList"))
    {
    @Html.LabelFor(d => d.ProductName)
    @Html.TextBoxFor(d => d.ProductName)
    <br />
    @Html.LabelFor(d => d.Amount)
    @Html.TextBoxFor(d => d.Amount)
    <br />
    @Html.LabelFor(d => d.UnitPrice)
    @Html.TextBoxFor(d => d.UnitPrice)
    <hr />
    <a href="#" class="deleteRow">delete</a>
    }
    </div>

    注意が必要なのはHtmlです.BeginCollectionItem(「Order.OrderDetailList」)のパラメータ名は、OrderDetailがホーム・ページに表示されたときの名前(name)の接頭辞であるため、非常に重要です.また、この名前には中括弧のペア「[]」が含まれており、製品名ProductNameなどのGuidの値があり、クライアント名では次の可能性があります.
        type="text" 
        value="" 
        name="Order.OrderDetailList[5c9f0287-82a2-41f3-96b4-9c8b2459527c].ProductName">
     
    四.ホームフェースの設定
    依存モデルOrderDetailの介入があるため、マスターモデルの名前もすべて接頭辞を付けなければならない.そうしないと、本来正常なマスターモデルでもコミットされたデータをマスターエンティティクラスに対応できない.原因は不明である.
    <label for="@string.Format("Order.{0}", "Description")">    </label>
    @Html.TextBox(string.Format("Order.{0}", "Description"))

    ついでに、ドロップダウン・ボックスのバインド方法を挙げます.
    //Controller 
    var CategoryItems = new List<Category>() {
    new Category(){
    CategoryID = 10,
    CategoryName = " "
    },
    new Category(){
    CategoryID = 11,
    CategoryName = " "
    }
    };
    ViewData["Order.CategoryID"] = new SelectList(CategoryItems, "CategoryID", "CategoryName", "");


    //View
    @Html.DropDownList(string.Format("Order.{0}", "CategoryID"), @ViewData["Order.CategoryID"] as List<SelectListItem>, "-- --", new { })

    五.オーダー詳細の表示
    受注明細が表示される領域を計画するのは、受注の下にあるDivです.実際のプロジェクトでは、レイアウトを真剣に検討することができます.
    <fieldset>
    <legend> </legend>
    <div id="OrderDetailDiv">
    </div>
    </fieldset>

    六.「+」ボタンをクリックして新しい明細を動的にロードし、削除をサポートします.もちろん、リフレッシュはありません.
    @using (Ajax.BeginForm("CreateOrderDetail", "Home", new AjaxOptions()
    {
    HttpMethod = "POST",
    InsertionMode = InsertionMode.InsertAfter,
    UpdateTargetId = "OrderDetailDiv",
    OnSuccess = "SuccessCallBack"
    }))
    {
    <input type="submit" id="btnAddDetail" value=" + " />
    }

    サービス側にPost形式で要求を開始し、要求が成功すると、得られた戻り値(HTML部分ブロック)が「InsertAfter」方式で追加され、UpdateTargetIdで指定された領域に更新され、最後にOnSuccessで指定されたJS関数が実行される.
    七.プライマリ・モデル・フィールドは、各フィールド名に接頭辞を付ける必要があることに注意してください.
    @using (Html.BeginForm("CreateOrder", "Home", FormMethod.Post))
    {
    <input type="submit" value=" " />
    <hr />

    <label for="@string.Format("Order.{0}", "Description")">
    </label>
    @Html.TextBox(string.Format("Order.{0}", "Description"))
    <br />
    <br />

    <label for="@string.Format("Order.{0}", "CreatePerson")">
    </label>
    @Html.TextBox(string.Format("Order.{0}", "CreatePerson"))
    <br />
    <br />

    <label for="@string.Format("Order.{0}", "CreateDate")">
    </label>
    @Html.TextBox(string.Format("Order.{0}", "CreateDate"))

    <br />
    <br />
    <label for="@string.Format("Order.{0}", "CategoryID")">
    </label>
    @Html.DropDownList(string.Format("Order.{0}", "CategoryID"), @ViewData["Order.CategoryID"] as List<SelectListItem>, "-- --", new { })
    <br />
    <br />
    <fieldset>
    <legend> </legend>
    <div id="OrderDetailDiv">
    </div>
    </fieldset>
    }

     
    提案のデバッグ方法:火狐ブラウザのFireBugツールを採用して、IEブラウザのHttpWatchと