You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:42:17