Asp.Net Core Razor Pages中disabled属性输入框在ModelState验证失败返回页面后为空的原因排查
这个问题的核心是HTML中带disabled属性的表单控件不会被浏览器提交,具体原因和解决办法如下:
为什么会出现空值?
当你提交表单时,浏览器会自动忽略所有带有disabled属性的输入元素,不会把它们的值包含在提交的表单数据里。所以你的OnPost方法接收到的episode对象中,EpisodeFileName属性是空的。
当ModelState.IsValid为false返回页面时,Razor视图会优先从ModelState或者绑定的模型实例中读取值来渲染表单。因为提交时根本没传EpisodeFileName,模型里这个属性是空的,所以页面上的disabled输入框就显示为空了。
解决方案
根据你的需求,这里有几种可行的解决方式:
1. 用readonly替代disabled(最推荐)
readonly属性的输入框是不可编辑的,但会被表单正常提交,这样后端能拿到EpisodeFileName的值,返回页面时也能正确显示:
<div class="form-group"> <label>Current EpisodeFileName</label> <input readonly asp-for="@Model.Episode.EpisodeFileName" class="form-control" /> </div>
注意:readonly只对文本类输入控件有效,如果你使用其他控件类型,这个方法依然适用。
2. 在OnPost中重新加载原数据
如果必须保留disabled属性,那在返回页面之前,重新从服务中获取对应的Episode记录,把EpisodeFileName赋值回模型:
public IActionResult OnPost(Episode episode) { if (!ModelState.IsValid) { // 从服务获取原Episode的FileName var existingEpisode = _courseServices.GetEpisodeByEpisodeId(episode.Id); episode.EpisodeFileName = existingEpisode.EpisodeFileName; ModelState.AddModelError("","لطفا تمام فیلد ها را با دقت وارد کنید"); return Page(); } return Page(); }
或者如果你用[BindProperty]绑定Episode属性,可以直接更新这个属性:
[BindProperty] public Episode Episode { get; set; } public IActionResult OnPost() { if (!ModelState.IsValid) { var existingEpisode = _courseServices.GetEpisodeByEpisodeId(Episode.Id); Episode.EpisodeFileName = existingEpisode.EpisodeFileName; ModelState.AddModelError("","لطفا تمام فیلد ها را با دقت وارد کنید"); return Page(); } return Page(); }
3. 保留disabled输入框,同时添加隐藏字段
保留disabled的输入框用来显示给用户,同时添加一个隐藏字段来提交EpisodeFileName的值,这样即使disabled的输入框不被提交,隐藏字段会把值传送到后端:
<div class="form-group"> <label>Current EpisodeFileName</label> <input disabled asp-for="@Model.Episode.EpisodeFileName" /> <input type="hidden" asp-for="@Model.Episode.EpisodeFileName" /> </div>
这样提交时隐藏字段会携带EpisodeFileName的值,返回页面时Razor也能从模型中读取这个值渲染到disabled输入框里。
内容的提问来源于stack exchange,提问作者Hossein

