0

I have an object model and I am passing it to the view so that user can input their comments for some of the object's properties as a part of a survey.

I am able to receive what the user has entered for an object if I am only rendered one single object to the view. However, when I want to render multiple (a list) of objects to the view then I receive a null list of objects when the user click on the submit form.

Please see my code below:

This is my object model

public class SurveyViewModel
{
    public string Name { get; set; }
    public double PV { get; set; }
    public double QtyUsePerMonth { get; set; }
    public double TotalPVPerMonth { get; set; }
}

This is my view where I render the list of object

@model IEnumerable<WebApplication4.Models.SurveyViewModel>
@{
    ViewBag.Title = "Survey";
}
<h2>Survey</h2>
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "form1" }))
{
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.PV)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.QtyUsePerMonth)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.TotalPVPerMonth)
            </th>
            <th></th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                    @Html.HiddenFor(modelItem => item.Name)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.PV)
                    @Html.HiddenFor(modelItem => item.PV)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.QtyUsePerMonth)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.TotalPVPerMonth)
                </td>
            </tr>
        }
    </table>

    <input type="submit" value="Submit">
}

And this is my HttpPost method

[HttpPost]
public ActionResult Survey(List<Models.SurveyViewModel> model)
{
     ...
}

When the user click on the Submit button I got a null for model where I am expecting to see a list.

Please let me know what I am doing wrong.

Thank you for your help.

Hammad Sajid
  • 296
  • 1
  • 3
  • 12
CB4
  • 580
  • 2
  • 9
  • 23
  • 2
    You can't use `foreach` to [post a collection](http://stackoverflow.com/questions/19964553/mvc-form-not-able-to-post-list-of-objects) like that. You need an index. – Jasen Jan 10 '17 at 18:17
  • @Jasen can you give a snipped code for my case of how to use the index? – CB4 Jan 10 '17 at 18:26
  • The basic pattern is `for(int i = 0; i < length; i++) { Html.TextBoxFor(m => m.Collection[i].Property) }`. Here is [another good example](http://stackoverflow.com/a/29161796/2030565). – Jasen Jan 10 '17 at 18:33

1 Answers1

0

Normally, you can't post the list of objects to the controller in default model binder.

Best solution you can pass the object only based on Index to perform the CRUD operation in POST, and GET request you could get all list of objects. So in POST method it works if pass the object only.

If you want to post the list of object, you can achieve it by overriding the ModelBinder or using the FormCollection.

Here is an example, but to perform this way of operation we need to iterate and convert into the list. Because formcollection contains more number of items and not in the List type. The key of the property varies, because of html helper. Be aware when getting the value from formcollection.

[HttpPost]
public ActionResult Index(FormCollection model)
{
    List<SurveyViewModel> obj = new List<SurveyViewModel>();

    var name =Request.Form["item.Name"].Split(',').ToArray();
    var pv =Request.Form["item.PV"].Split(',').ToArray();

    //length must be same
    for (var i = 0; i < name.Length; i++)
    {
        obj.Add(new SurveyViewModel()
        {
            Name = name[i],
            PV = Convert.ToDouble(pv[i])
        });
    }

    return View();
}
Hammad Sajid
  • 296
  • 1
  • 3
  • 12
Balaji Marimuthu
  • 1,742
  • 9
  • 13