ASP.NET Core 3.1 Razor Pages如何实现SQL Server绑定下拉列表
ASP.NET Core 3.1 Razor Pages 实现City字段下拉列表(从SQL Server加载选项)
以下实现全为Razor Pages原生写法,无MVC相关逻辑:
第一步:准备城市选项数据源
两种方案二选一即可:- 单独维护城市选项表(推荐,方便统一管理可选值)
在Models目录下新增城市选项实体:
using System.ComponentModel.DataAnnotations; public class CityOption { [Key] public int Id { get; set; } [Required] public string CityName { get; set; } }在你项目的EF Core DbContext类中新增对应DbSet配置:
public DbSet<CityOption> CityOptions { get; set; }打开包管理器控制台执行迁移命令,更新本地SQL Server数据库生成表结构,之后手动在表中录入所有可选城市数据即可:
Add-Migration AddCityOptionTable Update-Database- 从已有Person表去重取城市值(无需新建表,适合不需要单独维护选项的场景)
不需要新增实体和表,后续查询时直接从Persons表去重取已录入的城市值作为选项即可。
- 单独维护城市选项表(推荐,方便统一管理可选值)
第二步:修改新增页面(Create)的后置代码Create.cshtml.cs
注入DbContext,新增下拉列表绑定属性,在页面加载、校验失败返回时加载城市选项:using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; // 保留原有using引用 public class CreateModel : PageModel { private readonly YourAppDbContext _context; // 替换为你项目中实际的DbContext类名 public CreateModel(YourAppDbContext context) { _context = context; } [BindProperty] public Person Person { get; set; } // 存储下拉选项的属性 public SelectList CitySelectList { get; set; } public async Task<IActionResult> OnGetAsync() { // 加载城市选项 await LoadCityOptions(); return Page(); } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { // 校验失败返回页面时必须重新加载选项,否则下拉框为空 await LoadCityOptions(); return Page(); } _context.Persons.Add(Person); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); } // 抽离公共的城市选项加载逻辑,避免重复写代码 private async Task LoadCityOptions(string selectedCity = null) { List<string> cityList; // 单独表方案用下面这段查询 cityList = await _context.CityOptions .OrderBy(c => c.CityName) .Select(c => c.CityName) .ToListAsync(); // 如果用Person表去重方案,注释上面的查询,改用下面这段 // cityList = await _context.Persons // .Where(p => !string.IsNullOrEmpty(p.City)) // .Select(p => p.City) // .Distinct() // .OrderBy(c => c) // .ToListAsync(); CitySelectList = new SelectList(cityList, selectedCity); } }第三步:修改Create.cshtml页面的City字段,替换原文本输入框为下拉框
把原有City字段的<input>标签替换为<select>标签,使用内置的select tag helper绑定选项:<div class="form-group"> <label asp-for="Person.City" class="control-label"></label> <select asp-for="Person.City" class="form-control" asp-items="Model.CitySelectList"> <option value="">--请选择城市--</option> </select> <span asp-validation-for="Person.City" class="text-danger"></span> </div>第四步:修改编辑页面(Edit)的后置代码Edit.cshtml.cs
逻辑和新增页一致,加载选项时传入当前Person已绑定的City值作为默认选中项:using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; // 保留原有using引用 public class EditModel : PageModel { private readonly YourAppDbContext _context; // 替换为你项目中实际的DbContext类名 public EditModel(YourAppDbContext context) { _context = context; } [BindProperty] public Person Person { get; set; } public SelectList CitySelectList { get; set; } public async Task<IActionResult> OnGetAsync(int? id) { if (id == null) return NotFound(); Person = await _context.Persons.FirstOrDefaultAsync(m => m.ID == id); if (Person == null) return NotFound(); // 加载城市选项,传入当前人员的城市作为默认选中值 await LoadCityOptions(Person.City); return Page(); } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { await LoadCityOptions(Person.City); return Page(); } _context.Attach(Person).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!PersonExists(Person.ID)) return NotFound(); throw; } return RedirectToPage("./Index"); } private bool PersonExists(int id) { return _context.Persons.Any(e => e.ID == id); } // 和新增页共用相同的选项加载逻辑 private async Task LoadCityOptions(string selectedCity = null) { List<string> cityList; // 单独表方案 cityList = await _context.CityOptions .OrderBy(c => c.CityName) .Select(c => c.CityName) .ToListAsync(); // Person表去重方案用这段 // cityList = await _context.Persons // .Where(p => !string.IsNullOrEmpty(p.City)) // .Select(p => p.City) // .Distinct() // .OrderBy(c => c) // .ToListAsync(); CitySelectList = new SelectList(cityList, selectedCity); } }第五步:修改Edit.cshtml页面的City字段,和新增页替换逻辑一致
把原有文本输入框替换为下拉框:<div class="form-group"> <label asp-for="Person.City" class="control-label"></label> <select asp-for="Person.City" class="form-control" asp-items="Model.CitySelectList"> <option value="">--请选择城市--</option> </select> <span asp-validation-for="Person.City" class="text-danger"></span> </div>
补充说明:如果需要强制用户选择城市,可以在Person类的City属性上添加
[Required(ErrorMessage = "请选择城市")]校验特性,表单提交时会自动触发非空校验。
内容的提问来源于stack exchange,提问作者wiedersehen
相关产品推荐
相关产品推荐

