Class sent to Post Action is null

I'm working on a view that presents all the records of class (Machine) where some of their properties could be updated.

For this, the view is working with an IEnumerable. These are the Get and Post methods:

Get:

public async Task<IActionResult> Test()
    {

        PopulateMachineTypeDropDownListStore();
        return View(await _context.Machines.AsNoTracking().ToListAsync());
    }

Post:

[HttpPost, ActionName("Test")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> TestPost(int id, [Bind("Id,StoreID,PUnit,Status")] Machine machine)
    {
        if (id != machine.Id)
        {
            return NotFound();
        }
        if (ModelState.IsValid)
        {
            try
            {
                _context.Update(machine);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!MachineExists(machine.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction("Index");
        }
        return View(machine);}

The problem is that the class sent to the Post Action is null (almost all their fields are zero or null except for the Id)

public async Task<IActionResult> TestPost(int id, [Bind("Id,StoreID,PUnit,Status")] Machine machine)

Question: So, I don't know how to correct this. Could there be something missing in the view?

@model IEnumerable<Application.Models.Machine>
@{
    ViewData["Title"] = "Test";

}
@foreach (var item in Model)
{
    <form asp-action="Test" asp-route-id="@item.Id" method="post">
        <table class="table">
            <tbody>
            <tr>
                <td>
                    <input type="hidden" asp-for="@item.Id" />
                    <div class="form-group">
                        <div class="col-md-10">
                            <input asp-for="@item.MchName" readonly class="form-control" />
                            <span asp-validation-for="@item.MchName" class="text-danger"></span>
                        </div>
                    </div>
                </td>
                <td>
                    <div class="form-group">
                        <div class="col-md-10">
                            <select asp-for="@item.StoreID" class="form-control" asp-items="ViewBag.StoreID">
                            </select>
                            <span asp-validation-for="@item.StoreID" class="text-danger"></span>
                        </div>
                    </div>
                </td>
                <td>
                    <div class="form-group">
                        <div class="col-md-10">
                            <input type="number" max="10" step=".1" asp-for="@item.PUnit" class="form-control" />
                            <span asp-validation-for="@item.PUnit" class="text-danger"></span>
                        </div>
                    </div>
                </td>
                <td>
                    <div class="form-group">
                        <div class="col-md-10">
                            <select name="Status" asp-for="@item.Status" class="form-control">
                                <option value="0">Operativo</option>
                                <option value="1">Nuevo Item</option>
                                <option value="2">Reparación</option>
                            </select>
                            <span asp-validation-for="@item.Status" class="text-danger"></span>
                        </div>
                    </div>
                </td>
                <td>
                    <input id="submit-data" type="submit" value="Update" class="btn btn-default" />
                </td>
            </tr>
        </tbody>
    </table>

</form>}

Thanks in advance

Upvotes: 0

Views: 60

Answers (1)

Sigge
Sigge

Reputation: 2172

Because the ModelBinder uses naming conventions for binding, try renaming the machine parameter of the TestPost() method to item.

 public async Task<IActionResult> TestPost(
            int id, [Bind("Id, StoreID, PUnit,Status")] Machine item)
    {
        //... 
    }

Alternatively, in your View, you could rename the item variable to machine, so it matches the expected parameter name:

@foreach (var machine in Model)
{ ...  }

The docs describe this summarily:

Model binding looks for the pattern parameter_name.property_name to bind values to properties

Lastly, leave out the name attribute in your Status dropdown, which would impede modelbinding. Just let asp-for do the work:

<select asp-for="@item.Status" class="form-control">

I don't really know how you fill the Store dropdown, but you should at least see the PUnit and Status properties being filled up this way.

Upvotes: 1

Related Questions