ASP.NET Core 8 多选下拉列表CRUD实现求助
ASP.NET Core 8 完整CRUD示例(含多选下拉+X.PagedList)
1. 准备工作
- 安装所需NuGet包:
Microsoft.EntityFrameworkCore.SqlServer、X.PagedList.Mvc.Core、Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation(开发环境使用)
2. 数据模型
// Person.cs public class Person { public int Id { get; set; } public string FirstName { get; set; } = string.Empty; // 用逗号分隔存储选中的选项,例如"A,C" public string SelectedOptions { get; set; } = string.Empty; // 视图层用于展示选中选项的列表 public List<string> SelectedOptionsList => SelectedOptions.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(); } // 选项常量(也可存入数据库,此处简化实现) public static class OptionConstants { public static List<string> AllOptions => new List<string> { "A", "B", "C" }; }
3. 数据库上下文
// AppDbContext.cs public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Person> People { get; set; } }
Program.cs 配置
var builder = WebApplication.CreateBuilder(args); // 配置SQL Server数据库连接 builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 添加X.PagedList支持 builder.Services.AddControllersWithViews().AddXpagedList(); var app = builder.Build(); // 开发环境初始化数据库 using (var scope = app.Services.CreateScope()) { var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>(); dbContext.Database.EnsureCreated(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
appsettings.json 添加连接字符串
"ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MultiSelectDemo;Trusted_Connection=True;MultipleActiveResultSets=true" }
4. 控制器实现
public class HomeController : Controller { private readonly AppDbContext _context; public HomeController(AppDbContext context) { _context = context; } // 分页列表页 public async Task<IActionResult> Index(int? page) { var pageNumber = page ?? 1; var pageSize = 5; var people = await _context.People.ToPagedListAsync(pageNumber, pageSize); return View(people); } // 跳转创建页 public IActionResult Create() { ViewBag.AllOptions = OptionConstants.AllOptions; return View(); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(Person person, List<string> selectedOptions) { if (ModelState.IsValid) { person.SelectedOptions = string.Join(',', selectedOptions ?? new List<string>()); _context.Add(person); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } ViewBag.AllOptions = OptionConstants.AllOptions; return View(person); } // 跳转编辑页 public async Task<IActionResult> Edit(int? id) { if (id == null) return NotFound(); var person = await _context.People.FindAsync(id); if (person == null) return NotFound(); ViewBag.AllOptions = OptionConstants.AllOptions; return View(person); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, Person person, List<string> selectedOptions) { if (id != person.Id) return NotFound(); if (ModelState.IsValid) { try { person.SelectedOptions = string.Join(',', selectedOptions ?? new List<string>()); _context.Update(person); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!PersonExists(person.Id)) return NotFound(); else throw; } return RedirectToAction(nameof(Index)); } ViewBag.AllOptions = OptionConstants.AllOptions; return View(person); } // 跳转删除确认页 public async Task<IActionResult> Delete(int? id) { if (id == null) return NotFound(); var person = await _context.People.FirstOrDefaultAsync(m => m.Id == id); if (person == null) return NotFound(); return View(person); } [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(int id) { var person = await _context.People.FindAsync(id); if (person != null) _context.People.Remove(person); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } private bool PersonExists(int id) { return _context.People.Any(e => e.Id == id); } }
5. 视图实现
Index.cshtml(分页列表页)
@model X.PagedList.IPagedList<Person> @using X.PagedList.Mvc.Core; @{ ViewData["Title"] = "人员列表"; } <h1>人员列表</h1> <p> <a asp-action="Create">新增</a> </p> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.First().FirstName)</th> <th>选中选项</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.FirstName)</td> <td>@string.Join(", ", item.SelectedOptionsList)</td> <td> <a asp-action="Edit" asp-route-id="@item.Id">编辑</a> | <a asp-action="Delete" asp-route-id="@item.Id">删除</a> </td> </tr> } </tbody> </table> <!-- 分页控件 --> <div class="pagination"> 第 @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) 页,共 @Model.PageCount 页 @Html.PagedListPager(Model, page => Url.Action("Index", new { page })) </div>
Create.cshtml(创建表单)
@model Person @{ ViewData["Title"] = "新增人员"; var allOptions = ViewBag.AllOptions as List<string>; } <h1>新增人员</h1> <div class="row"> <div class="col-md-4"> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="FirstName" class="control-label"></label> <input asp-for="FirstName" class="form-control" /> <span asp-validation-for="FirstName" class="text-danger"></span> </div> <div class="form-group"> <label>选择选项</label> <select multiple class="form-control" name="selectedOptions"> @foreach (var option in allOptions) { <option value="@option">@option</option> } </select> <small class="text-muted">按住Ctrl键可多选</small> </div> <div class="form-group"> <input type="submit" value="创建" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">返回列表</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
Edit.cshtml(编辑表单)
@model Person @{ ViewData["Title"] = "编辑人员"; var allOptions = ViewBag.AllOptions as List<string>; var selectedValues = Model.SelectedOptionsList; } <h1>编辑人员</h1> <div class="row"> <div class="col-md-4"> <form asp-action="Edit"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input type="hidden" asp-for="Id" /> <div class="form-group"> <label asp-for="FirstName" class="control-label"></label> <input asp-for="FirstName" class="form-control" /> <span asp-validation-for="FirstName" class="text-danger"></span> </div> <div class="form-group"> <label>选择选项</label> <select multiple class="form-control" name="selectedOptions"> @foreach (var option in allOptions) { <option value="@option" @(selectedValues.Contains(option) ? "selected" : "")>@option</option> } </select> <small class="text-muted">按住Ctrl键可多选</small> </div> <div class="form-group"> <input type="submit" value="保存" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">返回列表</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
Delete.cshtml(删除确认页)
@model Person @{ ViewData["Title"] = "删除人员"; } <h1>确认删除</h1> <h3>确定要删除该人员吗?</h3> <div> <dl class="row"> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.FirstName) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.FirstName) </dd> <dt class="col-sm-2"> 选中选项 </dt> <dd class="col-sm-10"> @string.Join(", ", Model.SelectedOptionsList) </dd> </dl> <form asp-action="Delete"> <input type="hidden" asp-for="Id" /> <input type="submit" value="删除" class="btn btn-danger" /> | <a asp-action="Index">返回列表</a> </form> </div>
内容的提问来源于stack exchange,提问作者joegreen
相关产品推荐
相关产品推荐

