Asp.net core MVC (Razor Pages) - Bind nested list of objects on post

Viewed 2749

I have an edit page which edits an object. This object has a nested list of another object.

EditModel:

public class EditModel : BasePageModel
{
    [BindProperty]
    public Update.Command Command { get; set; }

    public async Task<IActionResult> OnGetAsync(Update.Query query)
    {
        Command = await Mediator.Send(query);

        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        await Mediator.Send(Command); // Command.ListA is null here. ???

        return RedirectToPage("Index");
    }
}

Edit.cshtml:

<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <div class="form-group">
        <label asp-for="Command.Id"></label>
        <input asp-for="Command.Id" readonly class="form-control"/>
    </div>

  // other non-relevant properties...

  <table class="table">
         <thead>
            <tr>
                <th>
                    <label asp-for="Command.ListA[0].Date"></label>
                </th>
                <th>
                    <label asp-for="Command.ListA[0].Value"></label>
                </th>
            </tr>
         </thead>
         <tbody>

            @foreach (var item in Model.Command.ListA)
            {
                <tr>
                    <td>
                        <input type="date" asp-for="@item.Date"/>
                    </td>
                    <td>
                        <input type="number" asp-for="@item.Value"/>
                    </td>
                </tr>
            }

            </tbody>
        </table>

        <div class="form-group">
            <input type="submit" value="Save" class="btn btn-primary"/>
        </div>

When I post back using the submit button. My listA is null. Could somebody help me understand why my command doesn't bind?

Many thanks for your help!

1 Answers

It's expected from MVC model binding. The @ sign is to get the data out, not to bind it in. You have to target the asp-for to the actual property.

Instead of using foreach, change it to:

@for (int i = 0; i < Model.Command.ListA.Count; i++)
{
    <tr>
        <td>
            <input type="date" asp-for="Command.ListA[i].Date"/>
        </td>
        <td>
            <input type="number" asp-for="Command.ListA[i].Value"/>
        </td>
    </tr>
}

Make sure that your ListA is an actual list, not an IEnumerable

Related