简体   繁体   中英

Why is my HttpPost action method not receiving a List<model> from the view

I have created a form that edits a list of notes. The form displays the Id of each note along with the message it contains. This works.

The problem is that after changing the messages in these notes and submitting the changes, the form is sent but I receive an empty list of models from the HttpPost action-method parameter.

I looked through many similar questions but a common problem was that the view model did not contain public properties. Mine does. I can't see where the problem is. I am a beginner to programming so I apologise if the problem is too obvious.

// My View Model

public class NoteViewModel
{
    public int Id { get; set; }
    public string Message { get; set; }
}

// My Post Action method

[HttpPost]
public IActionResult EditNotes(List<NoteViewModel> model)
{   
    foreach (var item in model)
    {
        // Create a note, and copy values from model
        Note note = new Note
        {
            Id = item.Id,
            Message = item.Message
        };

        // Update note in database.
        noteRepository.Update(note);
    }
    return RedirectToAction("NotePage", "Home");
}

// My View EditNote.cshtml

@model List<MyWebsite.ViewModels.NoteViewModel>

<form asp-action="EditNotes" method="post">
    @foreach (var note in Model)
    {
        <label asp-for="@note.Id">@note.Id</label>
        <label asp-for="@note.Message">Message</label>
        <input asp-for="@note.Message" value="@note.Message" />
    }
    <button type="submit" class="btn btn-success">Submit</button>
</form>

I expect to receive a list of models that contain the notes, but I receive an empty list here

public IActionResult EditNotes(List<NoteViewModel> model)
{
    // model is empty
    // model.Count() gives 0.
}

This:

@model List<MyWebsite.ViewModels.NoteViewModel>

<form asp-action="EditNotes" method="post">
    @foreach (var note in Model)
    {
        <label asp-for="@day.Id">@note.Id</label>
        <label asp-for="@note.Message">Message</label>
        <input asp-for="@day.Message" value="@day.Message" />
    }
    <button type="submit" class="btn btn-success">Submit</button>
</form>

Needs to be this:

@model List<MyWebsite.ViewModels.NoteViewModel>

<form asp-action="EditNotes" method="post">
    @for( Int32 i = 0; i < this.Model.Count; i++ ) {
        <label>@Model[i].Id</label>
        <input asp-for="@Model[i].Id" type="hidden" />
        <label asp-for="@Model[i].Message">Message</label>
        <input asp-for="@Model[i].Message" />
    }
    <button type="submit" class="btn btn-success">Submit</button>
</form>

This is because ASP.NET Core MVC's model-binding uses Expression<Func<TModel,TProperty>> for generating the name="" attributes, which means it needs a full expression to get from TModel to the property it's bound to.

The tag-helper will also generate the value="" attribute for you, you don't need to specify it manually. Ditto the <label> 's text too (especially if you use the [Display] or [DisplayName] attributes on the model properties.

You should iterate with a for block at the view side. For example see this example:

<form asp-action="EditBulk" , method="post">
    <table class="table">
        <thead>
            <tr>
                <th>
                    <label id="noteTextLbl">Note Text</label>
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @for (int i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td>
                        <input asp-for="@Model[i].NoteId" type="hidden" />
                        <input asp-for="@Model[i].NoteText" />
                    </td>
                    <td>
                        <a asp-action="Edit" asp-route-id="@Model[i].NoteId">Edit</a> |
                        <a asp-action="Details" asp-route-id="@Model[i].NoteId">Details</a> |
                        <a asp-action="Delete" asp-route-id="@Model[i].NoteId">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <button type="submit">Send changes</button>
</form>

I don't know why, but this just works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM