问题
I am trying to bind unknown amount of checkboxes to a list of booleans. After hours of searching I havn't found any solution.
This is the relevent part of code in my view:
@foreach (Device d in Data.GetDevices())
{
<label asp-for="NewRegistration.Devices">@d.Name</label>
<input asp-for="NewRegistration.Devices" class="checkbox" type="checkbox" />
}
The loop works but when i changed the type if the input to checkbox it gave me this exeption:
InvalidOperationException: Unexpected 'asp-for' expression result type 'System.Collections.Generic.List`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' for . 'asp-for' must be of type 'System.Boolean' if 'type' is 'checkbox'.
The list i try to put my data in contains the following code:
private List<bool> _devices;
public List<bool> Devices
{
get { return _devices; }
set {_devices = value; }
}
So my question is how do I add values from these checkboxes into my list of booleans. When i don't specify the type of the input's, I dont get any errors but the type of the input is text. If i enter true or false in these inputboxes my code works fine. But I want a checkbox instead of asking the user to enter true or false.
Thank you for your time!
edit: My question proves hard to explain. I'm validating the form and binding it to an instance of the registration class defined in a presentation model PMRegistration. I will put the full code below if the snippets are not clear enough
Registration class:
public class Registration
{
public int Id { get; set; }
[Required(ErrorMessage = "required field")]
[MaxLength(50, ErrorMessage = "To long")]
[DisplayName("Name")]
public string Name { get; set; }
[Required(ErrorMessage = "required field")]
[MaxLength(50, ErrorMessage = "To long")]
[DisplayName("Firstname")]
public string FirstName { get; set; }
[Required(ErrorMessage = "required field")]
[Range(1,110 ,ErrorMessage = "To long")]
public string Age { get; set; }
[Required(ErrorMessage = "required field")]
[EmailAddress(ErrorMessage ="Not a valid email address")]
public string Email { get; set; }
[Required(ErrorMessage = "required field")]
[DisplayName("slot1")]
public int Slot1SessionId { get; set; }
[Required(ErrorMessage = "required field")]
[DisplayName("slot2")]
public int Slot2SessionId { get; set; }
[Required(ErrorMessage = "required field")]
[DisplayName("slot3")]
public int Slot3SessionId { get; set; }
private List<bool> _devices;
public List<bool> Devices
{
get { return _devices; }
set {_devices = value; }
}
[Required(ErrorMessage = "required field")]
[DisplayName("Organization")]
public int OrganizationId { get; set; }
public bool ClosingParty { get; set; }
}
My view looks like this:
@using week3.Models;
@model week3.Models.PresentationModels.PMRegistration
<div>
<h1>New Registration</h1>
<h2>registration</h2>
</div>
<form class="form-group" asp-controller="Registration" asp-action="New" method="post">
<div>
<label asp-for="NewRegistration.Name">Name:</label>
<input asp-for="NewRegistration.Name" class="form-control" value="@Model.NewRegistration.Name" />
<span asp-validation-for="NewRegistration.Name" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.FirstName">Firstname:</label>
<input asp-for="NewRegistration.FirstName" class="form-control" value="@Model.NewRegistration.FirstName" />
<span asp-validation-for="NewRegistration.FirstName" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.Age">Age:</label>
<input asp-for="NewRegistration.Age" class="form-control" value="@Model.NewRegistration.Age" />
<span asp-validation-for="NewRegistration.Age" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.Email">Email:</label>
<input asp-for="NewRegistration.Email" class="form-control" value="@Model.NewRegistration.Email" />
<span asp-validation-for="NewRegistration.Email" class="text-danger"></span>
</div>
<div>
<div>Pick your sessions</div>
<label asp-for="NewRegistration.Slot1SessionId" class="form-label">Slot1:</label>
<select asp-for="NewRegistration.Slot1SessionId" class="form-control" asp-items="@Model.getSessionNamesBySlot(1)" value="@Model.NewRegistration.Slot1SessionId"></select>
<span asp-validation-for="NewRegistration.Slot1SessionId" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.Slot2SessionId">Slot2:</label>
<select asp-for="NewRegistration.Slot2SessionId" class="form-control" asp-items="@Model.getSessionNamesBySlot(2)" value="@Model.NewRegistration.Slot2SessionId"></select>
<span asp-validation-for="NewRegistration.Slot2SessionId" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.Slot3SessionId">Slot3:</label>
<select asp-for="NewRegistration.Slot3SessionId" class="form-control" asp-items="@Model.getSessionNamesBySlot(3)" value="@Model.NewRegistration.Slot3SessionId"></select>
<span asp-validation-for="NewRegistration.Slot3SessionId" class="text-danger"></span>
</div>
<div>are you wearing dangerous accessoires?</div>
@foreach (Device d in Data.GetDevices())
{
<label asp-for="NewRegistration.Devices[0]">@d.Name</label>
<input asp-for="NewRegistration.Devices[0]" class="checkbox" type="checkbox" />
}
<div>
<label asp-for="NewRegistration.OrganizationId">Organization:</label>
<select asp-for="NewRegistration.OrganizationId" asp-items="@Model.getOrganizations()" class="form-control"></select><br />
<span asp-validation-for="NewRegistration.OrganizationId" class="text-danger"></span>
</div>
<div>
<label asp-for="NewRegistration.ClosingParty">Are you coming to the closing party?</label>
<input asp-for="NewRegistration.ClosingParty" />
<span asp-validation-for="NewRegistration.ClosingParty" class="text-danger"></span>
</div>
<input type="submit" class="btn btn-default" value="Register" />
</form>
回答1:
Reason for error
Your error is because you have this: asp-for="NewRegistration.Devices"
. That is not valid because the tag is input of type checkbox so asp-for
is expecting a boolean and you are sending it a list of booleans.
Solution
This will create checkboxes for your devices:
@foreach (Device d in Data.GetDevices())
{
@Html.CheckBox(item);
}
But my assumption is you want the user to select these checkboxes and then post them back to you, if that is the case then you need to do this:
You need to create a model like this:
public class Device
{
public string Name { get; set; }
}
public class DevicesCollectionModel
{
public List<Device> AvailableDevices { get; set; }
public List<Device> SelectedDevices { get; set; }
}
Populate the DevicesCollectionModel.AvailableDevices
and pass it to your view.
Then in your view, create a checkbox for each device in AvailableDevices
. Pay attention to the name
attribute of the input tag below:
@foreach (var item in Model.AvailableDevices)
{
<div class="checkbox">
<label>
<input type="checkbox"
name="SelectedDevices"
value="@item.Name" /> @item.Name
</label>
</div>
}
Then in your controller, in post, you will need to access the SelectedDevices
property to figure out what the user has selected.
Furthermore, you can create separate models: one for sending to the user and one the controller receives from the user. The model you pass to your view can just have the AvailableDevices
and the model you get in your controller on post can have SelectedDevices
. MVC will bind it for you using the name
attribute from the input tag.
来源:https://stackoverflow.com/questions/41511664/asp-net-mvc-putting-checkbox-data-in-a-list-of-booleans