0

It seems like a lot of people have this issue, but I haven't found a solution to my specific case yet.

I start by sending my tickets to my view

[HttpGet]
    public ActionResult AddPopcorn()
    {
        List<Ticket> tickets = new List<Ticket>();
        // Fill the list with tickets
        return View("AddPopcorn", tickets);
    }

In the view I display the tickets with a form and checkbox. The view displays the tickets correctly.

@model List<Domain.Entities.Ticket>

@{
    ViewBag.Title = "AddPopcorn";
}

<body>
  // Html stuff
        @using (Html.BeginForm("AddPopcorn", "Ticket", FormMethod.Post))
        {
            <table>
                @foreach (var item in Model)
                {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.TicketID)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Price)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.TicketType)
                    </td>
                    <td>
                        @Html.CheckBoxFor(modelItem => item.Popcorn)
                    </td>
                </tr>
                }
            </table>
            <input type="submit" value="Voeg toe!" />
        }
    </div>
</body>

If people check the checkbox, I want the value 'Popcorn' to be true. So I want the view to return a list of tickets with updated values for popcorn based on the checkbox.

    [HttpPost]
    public ActionResult AddPopcorn(List<Ticket> model)
    {
        foreach (var item in model)
        {
            if (item.Popcorn == true)
            {
                item.Price = item.Price + 5;
            }
        }
        return RedirectToAction("Payment", "Payment");
    }

However, the model returned to AddPopcorn is null. I can't seem to figure out why.

Rodi
  • 122
  • 8

2 Answers2

1

Try changing your foreach loop to a for:

for (int i = 0; i < Model.Count; i++)
{
  <tr>
    <td>
      @Html.DisplayFor(x => Model[i].TicketID)
    </td>

    <td>
      @Html.DisplayFor(x => Model[i].Price)
    </td>

    // etc 

    <td>
      @Html.CheckBoxFor(x => Model[i].Popcorn)
    </td>        
  </tr>   
}

The default model binder uses a specific convention to work out how to bind a list of items, such as Model[0].Popcorn (name). You could check if the HTML for the CheckBox has a name attribute set to that format.

Other than using for, you could also specify a custom EditorTemplate for your Ticket object.

Matt Griffiths
  • 1,142
  • 8
  • 26
0

This is because your form isn't actually posting any data back to the controller.

You need input elements to actually be able to retrieve data from the form.

Instead, on the controller, access the model this way:

var model = this.Model

The form will only send data that you've got in input tags, e.g.

<input type="text" name="first_name" />
Clint
  • 6,133
  • 2
  • 27
  • 48
  • Is there a way to make it send all the data that was send to the view back? I've fixed it now by updating my list from my previous model with tempdata, List ticketList = (List)TempData["Tickets"]; But that is not the prettiest solutions. – Rodi Mar 08 '18 at 22:16