ASP.NET Core编辑页下拉框未重选时无法保留原值问题
问题描述
CREATE(新建)页面部署2个下拉选择框,新建页选中下拉选项提交后,数据可正常绑定写入数据库。但打开EDIT(编辑)页修改任意内容(无论是否修改下拉框字段),下拉框都会回退到---select---默认占位选项。必须每次编辑时重新选中两个下拉框的选项,才能正常绑定更新后的值;若仅修改其中一个字段,未操作的另一个下拉框值就会回退到默认---select ***---状态。
复现步骤
- 新建页内容提交完成后,首次点击进入编辑页,初始提交的绑定值可正常显示:

- 仅修改Specialty(专科)字段为'Anesthesiology'后点击UPDATE(更新)按钮,再次进入编辑页时,Res Type字段会回退到默认---Select---状态:

- 若在编辑页不做任何修改直接点击UPDATE按钮提交,再次进入页面查看时两个下拉框都会回退到默认---Select---状态:

现有代码
编辑页视图(EDIT Page Model)代码
<div class="mb-3"> <label asp-for="InfoSite.Specialty"></label> <select asp-for="InfoSite.Specialty" id="Select1" class="form-select"> <option value="">---Select Specialty---</option> @if (Model.DisplayMDSpecialtyData != null) { @foreach(var item1 in Model.DisplayMDSpecialtyData) { <option value="@item1.ID" selected="@(item1.ID.ToString()==Model.InfoSite.Specialty?true:false)" disabled="@(item1.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item1.Description</option> } } </select> </div> </td> <td style="width: 25%"> <div class="mb-3"> <label asp-for="InfoSite.ResType"></label> <select asp-for="InfoSite.ResType" id="Select2" class="form-select"> <option value="">---Select Residence Type---</option> @if (Model.DisplayResTypeData != null) { @foreach (var item2 in Model.DisplayResTypeData) { <option value="@item2.ID" selected="@(item2.ID.ToString()==Model.InfoSite.ResType?true:false)" disabled="@(item2.ID.ToString()==Model.InfoSite.ResType?true:false)">@item2.Description</option> } } </select> </div>
Edit.cshtml.cs 后台代码
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using PHECWeb.Data; using PHECWeb.Model; namespace PHECWeb.Pages.InfoSites; [BindProperties] public class EditModel : PageModel { private readonly ApplicationDbContext _db; public InfoSite InfoSite { get; set; } public EditModel(ApplicationDbContext db) { _db = db; } public IEnumerable<MDSpecialty> DisplayMDSpecialtyData { get; set; } public IEnumerable<ResType> DisplayResTypeData { get; set; } public void OnGet(int? ID) { InfoSite = _db.InfoSite.Find(ID); DisplayMDSpecialtyData = _db.MDSpecialty.ToList(); DisplayResTypeData = _db.ResType.ToList(); } public async Task<IActionResult> OnPost() { if (ModelState.IsValid) { _db.InfoSite.Update(InfoSite); await _db.SaveChangesAsync(); TempData["success"] = "Site Information updated successfully."; return RedirectToPage("Index"); } return Page(); } }
问题根因
- 视图代码中给当前选中的下拉选项加了
disabled属性,浏览器默认不会将被禁用的表单控件值提交到后端,未手动重新选择的下拉框值不会随表单发送,后端接收到对应字段为空,更新数据库时就会存入空值,下次打开页面自然回到默认占位选项。 - OnPost方法未处理模型校验失败的场景,校验不通过直接返回页面时,两个下拉框的数据源未重新加载,会出现下拉选项为空的异常。
修复方案
1. 修改视图层下拉框代码,移除选中项的disabled属性
找到两个下拉框内option标签上的disabled="@(item1.ID.ToString()==Model.InfoSite.Specialty?true:false)"和disabled="@(item2.ID.ToString()==Model.InfoSite.ResType?true:false)"代码,全部删除。
作用: 移除选中项的禁用状态后,当前选中的下拉值会正常随表单提交到后端,不会出现未手动操作的下拉框传空值的问题。
修改完成后的两个下拉框代码如下:
<div class="mb-3"> <label asp-for="InfoSite.Specialty"></label> <select asp-for="InfoSite.Specialty" id="Select1" class="form-select"> <option value="">---Select Specialty---</option> @if (Model.DisplayMDSpecialtyData != null) { @foreach(var item1 in Model.DisplayMDSpecialtyData) { <option value="@item1.ID" selected="@(item1.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item1.Description</option> } } </select> </div>
<div class="mb-3"> <label asp-for="InfoSite.ResType"></label> <select asp-for="InfoSite.ResType" id="Select2" class="form-select"> <option value="">---Select Residence Type---</option> @if (Model.DisplayResTypeData != null) { @foreach (var item2 in Model.DisplayResTypeData) { <option value="@item2.ID" selected="@(item2.ID.ToString()==Model.InfoSite.ResType?true:false)">@item2.Description</option> } } </select> </div>
2. 补全OnPost方法逻辑,加载校验失败场景的下拉数据源
找到Edit.cshtml.cs中的OnPost方法,在return Page();代码前添加两行下拉数据源加载代码,和OnGet方法中的加载逻辑保持一致。
作用: 表单提交校验不通过返回编辑页时,下拉框选项可以正常渲染,不会出现空下拉框的问题。
修改完成后的OnPost代码如下:
public async Task<IActionResult> OnPost() { if (ModelState.IsValid) { _db.InfoSite.Update(InfoSite); await _db.SaveChangesAsync(); TempData["success"] = "Site Information updated successfully."; return RedirectToPage("Index"); } // 校验失败时重新加载下拉框选项数据 DisplayMDSpecialtyData = _db.MDSpecialty.ToList(); DisplayResTypeData = _db.ResType.ToList(); return Page(); }
内容的提问来源于stack exchange,提问作者MelB
相关产品推荐
相关产品推荐

