简体   繁体   English

Asp.net MVC 4.5使用EditorFor,Button Click在ViewModel中将对象添加到列表

[英]Asp.net MVC 4.5 Add Object to List in ViewModel with EditorFor, Button Click

I'm currently working on an ASP.NET MVC 4.5 application. 我目前正在开发ASP.NET MVC 4.5应用程序。 I want to add objects to a List<T> dynamically on a button click, using a @Html.EditorFor and send the data to the Controller with a Form submit. 我希望使用@Html.EditorFor在按钮单击时动态地向List<T>添加对象,并使用表单提交将数据发送到Controller。

However, my problem, only the 1st element of the populated list gets sent to the controller when I submit my Form. 但是,我的问题是,当我提交表单时,只有填充列表的第一个元素被发送到控制器。

The area in my view where I add Elements looks like this: 我在视图中添加Elements的区域如下所示:

<div id="addTarget" data-target="@Url.Action("AddTarget", "Offer")">

    @for(var i = 0; i < Model.Targets.Count(); i++)
    {
        @Html.EditorFor(m => m.Targets[i])
    }
</div>

My Controller looks like that: 我的控制器看起来像这样:

...

public OfferVm NewOffer { get; set; } = new OfferVm();

[HttpGet]
public ActionResult Create()
{
    // ...here I add my first initial target to OfferVm
    NewOffer.Targets.Add(new TargetVm());

    return View(NewOffer);
}

public ActionResult AddTarget()
{
    // ...here I add a target to my NewOffer
    NewOffer.Targets.Add(new TargetVm());
    return PartialView("~/Views/Shared/EditorTemplates/TargetVm.cshtml");
}

[HttpPost]
public ActionResult Create(OfferVm offerVM)
{
   //... here only 1 target is in my offerVM
}

My OfferVm class looks like this: 我的OfferVm类看起来像这样:

public class OfferVm
{
    public OfferVm()
    {
        this.Targets = new List<TargetVm>();
    }

    public List<TargetVm> Targets { get; set; }
}

Do you have an idea how I can add a new target to my NewOffer.Targets List, and get the data in my controller, when I post the form? 您是否知道如何在我的NewOffer.Targets列表中添加新目标,并在发布表单时获取控制器中的数据?

The reason only the first TargetVm in your collection is being bound in the POST method, is that your AddTarget() method your calling to add a new item is generating form controls with name that are identical to those your have previously generated. 只有您的集合中的第一个TargetVm被绑定在POST方法中的原因是,您的AddTarget()方法调用添加新项目的方法是生成表单控件,其name与您之前生成的name相同。 Assuming TargetVm has a property named ID , then your have multiple elements with 假设TargetVm有一个名为ID的属性,那么你有多个元素

<input ... name="Targets[0].ID" ... />

and the DefaultModelBinder only binds the first name/value pair from the request, and ignores any subsequent duplicate names. 并且DefaultModelBinder仅绑定请求中的第一个名称/值对,并忽略任何后续重复的名称。 In order to bind to a collection, your name attributes need to have indexers that start at zero and be consecutive. 为了绑定到集合,您的name属性需要具有从零开始并且是连续的索引器。

<input ... name="Targets[0].ID" ... /> // first TargetVM
<input ... name="Targets[1].ID" ... /> // second TargetVM
<input ... name="Targets[2].ID" ... /> // third TargetVM

Note you can also include an extra input for each item in the collection - <input type="hidden" name="Targets.Index value="xx" /> (where xx is the value of the indexer) to bind non-consecutive indexers as discussed in Model Binding To A List . 请注意,您还可以为集合中的每个项目添加额外输入 - <input type="hidden" name="Targets.Index value="xx" /> (其中xx是索引器的值)绑定非连续在模型绑定到列表中讨论的索引器。

Using the EditorFor() method will not work in the case where your dynamically adding new collection items, unless you were to use javascript to update the value of the indexer in the name attribute when its added. 在动态添加新集合项的情况下,使用EditorFor()方法将不起作用,除非您在添加时使用javascript更新name属性中的索引器的值。

Solutions include using a javascript MVVM framework such as knockout , using the BeginCollectionItem() helper, or using a client side template and javascript to dynamically add new form controls. 解决方案包括使用javascript MVVM框架(如knockout) ,使用BeginCollectionItem()帮助程序,或使用客户端模板和javascript动态添加新的表单控件。 The latter two options are discussed in this answer , and a more complete example using BeginCollectionItem() is shown in this answer . 后两个选项中讨论该答案 ,并使用一个更完整的示例BeginCollectionItem()中示出这样的回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM