0

メインフォームからサブミットすると、部分的なビューからコントローラに動的に作成されたデータを渡す必要があります。ここで部分的なビューからコントローラにコレクションデータを渡す

は、部分的なビューを返すアクションです:

[HttpGet] 
public virtual PartialViewResult AddItem() 
{ 
    var item = new QuotedItem(); 
    ViewBag.StockID = new SelectList(db.StockItems.OrderBy(s => s.Name), "StockID", "Name"); 
    return PartialView("EditorTemplates/QuotedItem", item); 
} 

ここQuotedItemためEditorTemplateです:

@model StockSystem.Models.QuotedItem 

<div id="itemRow"> 

    <span> 
     @Html.DropDownListFor(model => model.StockID, null) 
     @Html.ValidationMessageFor(model => model.StockID, "", new { @class = "text-danger" }) 
    </span> 
    <span> 
     @Html.EditorFor(model => model.Price) 
     @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" }) 
    </span> 
    <span> 
     @Html.EditorFor(model => model.Quantity) 
     @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" }) 
    </span> 

    <a href="#" class="deleteSmall"></a> 

</div> 

は、ここでビューの:

@model StockSystem.Models.Quote 

@{ 
    ViewBag.Title = "Create"; 
} 

<h2>New Quote for @ViewBag.Customer</h2> 

<hr /> 
@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 
    @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
    @Html.Hidden("CustomerID", (object)ViewBag.CustomerID) 

    <div class="addItem"> 
     @Ajax.ActionLink(" ", "AddItem", 
     new AjaxOptions 
     { 
      UpdateTargetId = "editorRows", 
      InsertionMode = InsertionMode.InsertAfter, 
      HttpMethod = "GET" 
     }) 
    </div> 

    <div id="editorRows"> 
     @Html.EditorFor(q => q.QuotedItems) 
    </div> 

    <p></p> 

    <div> 
     <input class="add" type="submit" value="" /> 
     <a class="back" href="@Url.Action("Index", "Quotes", new { id = ViewBag.CustomerID })"></a> 
    </div> 
} 

ここでアクション作成です:

public ActionResult Create(int id) 
{ 
    var customer = db.Customers.Find(id); 
    ViewBag.CustomerID = id; 
    ViewBag.Customer = customer.CustomerName; 
    var quote = new Quote() { QuotedItems = new List<QuotedItem>() }; 
    return View(quote); 
} 
ここ

がQuotedItem用EFモデルです:

public partial class QuotedItem 
{ 
    public int QuotedItemID { get; set; } 
    public int QuoteID { get; set; } 
    public int StockID { get; set; } 
    public int Quantity { get; set; } 
    public decimal Price { get; set; } 

    public virtual Quote Quote { get; set; } 
    public virtual StockItem StockItem { get; set; } 
} 

と引用:

public partial class Quote 
{ 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
    public Quote() 
    { 
     this.QuotedItems = new HashSet<QuotedItem>(); 
    } 

    public int QuoteID { get; set; } 
    public int CustomerID { get; set; } 
    public int UserID { get; set; } 
    public System.DateTime QuoteDate { get; set; } 
    public string QuoteRef { get; set; } 

    public virtual Customer Customer { get; set; } 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 
    public virtual ICollection<QuotedItem> QuotedItems { get; set; } 
    public virtual User User { get; set; } 
} 

私は、ページに項目を追加することができますが、それらは提出上の引用には追加されません。

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "QuoteID,CustomerID,UserID,QuoteDate,QuoteRef,QuotedItems")] Quote quote) //, List<QuotedItem> items 
{ 
    if (ModelState.IsValid) 
    { 
     //quote.QuotedItems is empty, how do I bind this data and save to database?   
     db.Quotes.Add(quote); 
     db.SaveChanges(); 
     return RedirectToAction("Index", new { id = quote.CustomerID }); 
    } 

    return View(quote); 
} 

コレクションがコントローラに送信されていません。これはどうですか?

おかげ

編集:私はこれをしようと考えていた:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "QuoteID,CustomerID,UserID,QuoteDate,QuoteRef,QuotedItems")] Quote quote, List<QuotedItem> items) 
{ 
    if (ModelState.IsValid) 
    { 
     quote.QuotedItems = items; 
     db.Quotes.Add(quote); 
     db.SaveChanges(); 
     return RedirectToAction("Index", new { id = quote.CustomerID }); 
    } 

    return View(quote); 
} 

しかし、私はより良い方法がなければならないと思いました。私がこのアプローチを試していたとしても、これをコントローラーに送る方法はまだ完全にはわかっていないので、私はHtml.BeginForm()のパラメーターとして想定していますか?私はMVCをかなり新しくしていて、まだ慣習に慣れています。

答えて

0

メソッドシグネチャでBind属性を使用すると、QuotedItemsプロパティがコントローラアクションに送信されなくなります。

public ActionResult Create([Bind(Include = "QuoteID,CustomerID,UserID,QuoteDate,QuoteRef")] Quote quote) 

含めるリストにQuotedItemsプロパティ名を追加すると、この問題を解決する必要があります

public ActionResult Create([Bind(Include = "QuoteID,CustomerID,UserID,QuoteDate,QuoteRef,QuotedItems")] Quote quote) 

EDIT

あなたQuotedItemエディタテンプレートを見ることなく、それは確かに言うのは難しいですが、それリストに追加された各アイテムに、そのアイテムを構成する要素に一意のIDが設定されていない可能性があります。これがなければ、モデルバインダーはどの要素がコレクションのどのオブジェクトに属しているかを調べるのに苦労します。

は、これら二つの記事を見て、彼らは助けるかどうかを確認:あなたのテンプレートの各要素は、固有のIDを与えられるべき2

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

https://www.mattlunn.me.uk/blog/2014/08/how-to-dynamically-via-ajax-add-new-items-to-a-bound-list-model-in-asp-mvc-net/

編集索引はこれを行う良い方法です(項目GUIDがある場合)。各要素IDがその項目に固有である限り、それは機能するはずです。 [YOURINDEX]値上記のコードで

@model StockSystem.Models.QuotedItem 

<div id="itemRow"> 
<span> 
    @Html.DropDownListFor(model => model.StockID, null) 
    @Html.ValidationMessageFor(model => model.StockID, "", new { @class = "text-danger" }) 
</span> 
<span> 
    @Html.EditorFor(model => model.Price, new { htmlAttributes = new { id = $"[{YOURINDEX}].Price" } }) 
    @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" }) 
</span> 
<span> 
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { id = $"[{YOURINDEX}].Quantity" } }) 
    @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" }) 
</span> 

<a href="#" class="deleteSmall"></a> 

コレクションに追加される各新しいアイテムに対してインクリメントされる必要があるであろう。

このインデックスを実装してインクリメントする方法はあなた次第ですが、これがなぜ必要なのかを理解するために、前にリンクした2つの記事を読むことをお勧めします。

+0

私はすでにそれを試みました。コレクションはまだ空になります。 – Dom

+0

HttpGet Createアクションで 'QuoteItems'コレクションを初期化していますか? –

+0

Guy - Create Actionを表示するために質問を編集しました。 – Dom

関連する問題