ASP.NET Core Identity:如何在控制器获取Claims复选框选中值
Alright, let's break down the issues with your current code and fix it so you can properly capture which claims are selected in your controller.
The Core Problems
- Your
Claimclass (fromSystem.Security.Claims) doesn't have a property to track whether it's selected—you need a custom view model to add this state. - Using
foreachwithEditorForwon't generate the correct model binding names that ASP.NET MVC needs to map form data back to your collection.
Step 1: Update Your View Models
First, create a custom view model for individual claims to include an IsSelected property. Then update your RoleClaimsViewModel to use this new model instead of the raw Claim type:
// New view model for individual claims public class ClaimViewModel { public string Type { get; set; } public string Value { get; set; } // Include if you need the claim's value public bool IsSelected { get; set; } // Tracks if the claim is checked } // Updated role claims view model public class RoleClaimsViewModel { public string RoleName { get; set; } public List<ClaimViewModel> Claims { get; set; } }
Step 2: Fix the Razor View for Proper Model Binding
Replace your foreach loops with for loops—this ensures MVC generates form field names with indexes (like [0].Claims[0].IsSelected) that the model binder can recognize. Wrap everything in a form so you can submit the data:
@model List<IRSProject.Model.UserService.RoleClaimsViewModel> @using (Html.BeginForm("SaveSelectedClaims", "YourController", FormMethod.Post)) { @for (int roleIdx = 0; roleIdx < Model.Count; roleIdx++) { <div class="col-md-4 col-role"> <!-- Hidden field to preserve the role name on submit --> @Html.HiddenFor(m => m[roleIdx].RoleName) <input type="checkbox" id="Role_@roleIdx" /> <span>@Model[roleIdx].RoleName</span> <ul style="margin-left:1em"> @for (int claimIdx = 0; claimIdx < Model[roleIdx].Claims.Count; claimIdx++) { <li> <!-- Hidden field to keep the claim type --> @Html.HiddenFor(m => m[roleIdx].Claims[claimIdx].Type) <!-- Checkbox bound to the IsSelected property --> @Html.CheckBoxFor(m => m[roleIdx].Claims[claimIdx].IsSelected) <!-- Label for the checkbox --> @Html.LabelFor(m => m[roleIdx].Claims[claimIdx].IsSelected, Model[roleIdx].Claims[claimIdx].Type) </li> } </ul> </div> } <button type="submit" class="btn btn-primary">Save Selected Claims</button> }
Alternative: Use an Editor Template (Cleaner Views)
If you prefer cleaner markup, create an Editor Template for ClaimViewModel:
- Create a folder
Views/Shared/EditorTemplates - Add a file
ClaimViewModel.cshtmlwith this content:
@model IRSProject.Model.UserService.ClaimViewModel @Html.HiddenFor(m => m.Type) @Html.CheckBoxFor(m => m.IsSelected) @Html.LabelFor(m => m.IsSelected, Model.Type)
Then update your view to use EditorFor for the claims collection (still use a for loop for roles to preserve indexing):
@for (int roleIdx = 0; roleIdx < Model.Count; roleIdx++) { <div class="col-md-4 col-role"> @Html.HiddenFor(m => m[roleIdx].RoleName) <input type="checkbox" id="Role_@roleIdx" /> <span>@Model[roleIdx].RoleName</span> <ul style="margin-left:1em"> @Html.EditorFor(m => m[roleIdx].Claims) </ul> </div> }
Step 3: Capture the Selected Values in the Controller
Add a HttpPost action method that accepts your list of RoleClaimsViewModel. The model binder will automatically map the submitted form data to this model:
[HttpPost] public ActionResult SaveSelectedClaims(List<RoleClaimsViewModel> model) { if (ModelState.IsValid) { // Iterate through each role and its claims foreach (var roleClaims in model) { string roleName = roleClaims.RoleName; foreach (var claim in roleClaims.Claims) { bool isSelected = claim.IsSelected; string claimType = claim.Type; // Handle your business logic here: if (isSelected) { // This claim was checked—add it to the role, save to DB, etc. } else { // This claim was unchecked—remove it from the role, etc. } } } return RedirectToAction("YourSuccessAction"); } // Return to the view if validation fails return View(model); }
Key Takeaways
- Always use a custom view model when you need to track UI state (like
IsSelected) that isn't part of your domain model. - Use
forloops (instead offoreach) for collections in forms to ensure MVC generates correct model binding names. - Hidden fields preserve values like
RoleNameandClaim.Typethat you need to identify items after submission.
内容的提问来源于stack exchange,提问作者MrJahanbin

