Passing an array of ids from view pages to control

2020-02-13 07:22发布

问题:

I discovered that the ids are not getting passed through from the razor page to the controller. So my int[] userIds is empty but I don't know why or how to fix it. Please help.

Below is my code.

Account Controller:

public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    private readonly SignInManager<ApplicationUser> _signInManager;

    private readonly RoleManager<Role> _roleManager;

    public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, RoleManager<Role> roleManager)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _roleManager = roleManager;
    }

    public IActionResult Remove()
    {
        var users = _userManager.Users.OrderBy(o=> o.LastName).ToList();
        RemoveViewModel removeViewModel = new RemoveViewModel(users);
        return View(removeViewModel);
    }

    [HttpPost]
    public IActionResult Remove(int[] userIds)
    {

        if (userIds == null || userIds.Length==0)
        { 
            throw new System.ArgumentException("Array is empty", "original");
        }

        return Redirect("/Home/Index");
    }

view:

    @model WebApplication1.ViewModels.RemoveViewModel
<html>
<body>
    <form asp-controller="Account" asp-action="Remove" method="post">

            @foreach (var item in Model.Users)
            {
            <div>
                <label> @item.FirstName @item.LastName</label>
                <input type="checkbox" id="@item.Id" value="@item.Id" />
            </div>
            }


        <input type="submit" value=" Remove User" /><br>

    </form>

    </body>
</html>

ViewModel:

    namespace WebApplication1.ViewModels
{
    public class RemoveViewModel
    {
        public List<ApplicationUser> Users { get; set; }

        public RemoveViewModel(List<ApplicationUser> users)
        {
            Users = users; 
        }
    }
}

回答1:

The model binding in Asp.Net MVC is done by the name attribute of the html elements. So, add the name attribute to the input with the value of userIds. Hence, multiple elements with one name will bind to a single parameter of the same name that results in a list:

<input name="userIds" type="checkbox" id="@item.Id" value="@item.Id" />


回答2:

You need to indicate in your Html that the items belong to a list by giving them an 'index', and by doing that the model binding will be able to recognize that you're creating a list, and using the asp net core's tag helpers, it should generate the exact html you need for the binding:

<form asp-controller="Account" asp-action="Remove" method="post">

            @for (int i = 0; i < Model.Users.Count; i++)
            {
            <div>
                <label> @Model.Users[i].FirstName @Model.Users[i].LastName</label>
                <input type="checkbox" asp-for="@Model.Users[i].Id" />
            </div>
            }


        <input type="submit" value=" Remove User" /><br>

    </form>

I'd recommend looking in to the tag helpers as they can make your markup much more readable and less error prone as they generate a lot for you.

You're also also to write your own custom ones which can make life really easy!

Once you've tried the above I'd recommend you inspect the generated html in your browser debugger to see the html it creates and understand how the binding works.



回答3:

You need to use name property to pass selected ids to action with corresponding parameter name.

View:

@foreach (var item in Model.Users)
{
    <div>
        <label>@item.FirstName @item.LastName</label>
        <input type="checkbox" name="userIds" id="@item.Id" value="@item.Id" />
    </div>
}

Action:

[HttpPost]
public IActionResult Remove(int[] userIds)


回答4:

thanks guys, it was just as simple as adding the name or asp-for attribute to my input tag to ensure data binding.