0

Ich muss dynamisch erzeugte Daten aus einer Teilansicht an den Controller beim Senden aus dem Hauptformular übergeben.Übergabe der Sammeldaten von der Teilansicht zum Controller

Hier ist die Aktion, die die Teilansicht zurück:

[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); 
} 

die EditorTemplate für QuotedItem hier:

@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> 

Hier ist die Aussicht:

@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> 
} 

Hier ist die Aktion erstellen:

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); 
} 

Hier ist das EF-Modell für QuotedItem:

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; } 
} 

Und Zitat:

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; } 
} 

ich Elemente der Seite hinzufügen können, aber sie sind nicht auf das Zitat auf einreichen hinzugefügt.

[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); 
} 

Die Sammlung wird nicht an die Steuerung gesendet. Wie wird das gemacht?

Dank

Edit: Ich nachdachte zu versuchen:

[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); 
} 

Aber ich dachte, es muss einen besseren Weg geben. Wenn ich diesen Ansatz ausprobieren würde, bin ich mir immer noch nicht ganz sicher, wie ich das an den Controller senden soll, nehme ich als Parameter in Html.BeginForm() an? Ich bin ziemlich neu bei MVC und beschäftige mich immer noch mit den Konventionen.

Antwort

0

Durch die Verwendung des Bind-Attributs in der Methodensignatur verhindern Sie, dass die QuotedItems-Eigenschaft in die Controller-Aktion übertragen wird.

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

Hinzufügen der QuotedItems Eigenschaftsnamen in der Include-Liste sollte dieses Problem lösen:

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

EDIT

Ohne Ihre QuotedItem Editor-Vorlage zu sehen, ist es schwer, sicher zu sagen, aber es Es scheint, als ob Ihr Problem darin besteht, dass für jedes Ihrer Liste hinzugefügte Element keine eindeutige ID für die Elemente festgelegt ist, aus denen das Element besteht. Ohne dies wird der Modellbinder schwer herausfinden können, welches Element zu welchem ​​Objekt in der Sammlung gehört.

einen Blick auf diese beiden Artikel und sehen, ob sie helfen:

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/

Edit 2

Jedes Element in der Vorlage sollte eine eindeutige ID angegeben werden , ein Index ist ein guter Weg, dies zu tun, so sind Artikel GUIDs (wenn Sie sie haben); Aber solange jede Element-ID für dieses Element eindeutig ist, sollte es funktionieren.

@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> 

Im Code über den [YOURINDEX] Wert erhöht werden müßte, für jedes neues Element der Sammlung hinzugefügt.

Wie Sie diesen Index implementieren und inkrementieren, liegt an Ihnen, aber ich würde Ihnen empfehlen, die zwei Artikel zu lesen, mit denen ich zuvor verlinkt habe, um zu verstehen, warum dies notwendig ist.

+0

Ich habe das schon ausprobiert. Die Sammlung endet immer noch leer. – Dom

+0

initialisierst du die 'QuoteItems' Sammlung in der HttpGet Create Aktion? –

+0

Guy - Ich habe meine Frage bearbeitet, um die Create Action zu zeigen. – Dom

Verwandte Themen