0

I'm working in ASP.Net, and have an enumeration of viewmodels I want to display in a page. They contain a dropdown, and when said dropdown is updated, I have to take that enumeration of viewmodels, change the hirearchy inside it, and post it back with the changes. However, when I make my post, instead of sending the contained viewmodels, it sends an empty enumeration.

So far, I've tried switching my "foreach" in my view for a "for". I've also tried changing some names, seeing if the model binder was being the issue, but it doesn't seem so.

Here is the code for, respectively, the view, the viewmodel and the controller.

View

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken();
    for (int i = 0; i < Model.Count(); i++)
    {
        @Html.DropDownListFor(model => model.ElementAt(i).PickedNormId, Model.ElementAt(i).PickableNorms, UiText.Prosyn.N_A, htmlAttributes: new { @class = "form-control dropdown_search", @name="NormPicker"@*, @onchange = "this.form.submit();"*@ })
    }
<div>
    <input name="selectedNormList" type="submit">
</div>
}

ViewModel

public class NormPickerViewModel : ViewModel
{
    public SelectList PickableNorms { get; set; }

    public int PickedNormId { get; set; }
}

Controller

public virtual ActionResult Index()
{
    List<NormPickerViewModel> viewModels = new List<NormPickerViewModel>();

    viewModels.Add(new NormPickerViewModel()
    {
        PickableNorms = new SelectList(
            _normRepository.GetAll().Where(x => x.Depth == 1).ToList(),
            "Id",
            "Description"
        )
    });

    return View(viewModels);
}

[HttpPost]
public virtual ActionResult Index(IEnumerable<NormPickerViewModel> selectedNormList)
{
    // selectedNormList's count is always zero.
}

Normally, I'd expect to find the dropdowns I passed in the "Get" with their updated selected values, but what I'm getting is an empty enumeration.

mgrandmont
  • 45
  • 5
  • See the answers here https://stackoverflow.com/questions/19964553/mvc-form-not-able-to-post-list-of-objects – Jasen Apr 09 '19 at 23:25
  • @mgrandmont, did you try my source code? is there any issue? – Hien Nguyen Apr 11 '19 at 11:36
  • @Jasen's answer was the one that helped me! I never knew of the EditorForModel property, and it blows my mind how simple and efficient it is. Thanks! – mgrandmont Apr 11 '19 at 16:00

1 Answers1

1

I tried reproducing your source code, you need update 2 items and it worked:

Change from IEnumerable<NormPickerViewModel> selectedNormList to IEnumerable<NormPickerViewModel> normPickerViewModel in controller.

Add name for select tag (DropDownListFor) Name = "normPickerViewModel[" + i + "].PickedNormId" in cshtml file.

Here is Controller code

[HttpGet]
    public virtual ActionResult Index()
    {
        List<NormPickerViewModel> viewModels = new List<NormPickerViewModel>();

        viewModels.Add(new NormPickerViewModel()
        {
            PickableNorms = new SelectList(
                new List<dynamic> { new { Id = 1, Description = "Test1" }, new { Id = 2, Description = "Test2" } },
                "Id",
                "Description"
            )
        });

        viewModels.Add(new NormPickerViewModel()
        {
            PickableNorms = new SelectList(
                new List<dynamic> { new { Id = 3, Description = "Test3" }, new { Id = 4, Description = "Test4" } },
                "Id",
                "Description"
            )
        });

        return View(viewModels);
    }

    [HttpPost]
    public virtual ActionResult Index(IEnumerable<NormPickerViewModel> normPickerViewModel)
    {
        // selectedNormList's count is always zero.
        return null;
    }

and cshtml code

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken();
    for (int i = 0; i < Model.Count(); i++)
    {
        @Html.DropDownListFor(model => model.ElementAt(i).PickedNormId, Model.ElementAt(i).PickableNorms, "NA", htmlAttributes: new
        {
            @class = "form-control dropdown_search",
            Name = "normPickerViewModel[" + i + "].PickedNormId"@*, @onchange = "this.form.submit();"*@ 
        })
    }
    <div>
        <input name="selectedNormList" type="submit">
    </div>
}
Hien Nguyen
  • 21,001
  • 7
  • 35
  • 48