如何通过ASP注解正确验证Razor页面中的模态框局部视图?
问题解决:PartialView模态框验证失效
核心问题
尝试验证PartialView模态框中的「Name」字段但验证不生效,将Edit Partial从_PlayersTable移到Index后问题依旧;但Create模态框放在Index中可正常工作,想确认是否能保持现有渲染方式,还是需要新增ViewModel并在Index中逐个渲染。
原因分析
- 验证脚本绑定时机限制:jQuery Unobtrusive Validation仅在页面首次加载时,对当前DOM中存在的表单完成验证绑定。动态添加的表单(包括循环渲染的多个Edit模态框)不会自动触发验证绑定。
- 重复渲染的解析冲突:在_PlayersTable的循环中为每个Player渲染Edit Partial,会生成多个独立表单,可能导致验证元数据解析混乱;若Post请求返回无效的PartialView,新插入的表单也未重新绑定验证。
解决方案
不需要新增ViewModel,通过调整渲染方式和验证绑定逻辑即可解决,推荐以下两种方案:
方案一:AJAX动态加载Edit模态框(推荐)
避免一次性渲染所有模态框,提升页面性能同时确保验证正常工作。
1. 修改_PlayersTable中的Edit按钮
移除循环内的Partial渲染,改为点击按钮触发AJAX请求:
@using BGStats.ViewModels; @using BGStats.ViewModels.Players @using PagedList @model IPagedList<PlayerViewModel> @if (Model.Any()) { <table class="table"> <tr> <th scope="col">Player</th> <th scope="col">Name</th> <th> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addPlayer">Create</button> </th> </tr> @foreach (var player in Model) { <tr> <td>@player.Image</td> <td>@player.Name</td> <td> <button type="button" class="btn btn-warning edit-player-btn" data-player-id="@player.Id"> <i class="bi bi-pencil"></i> </button> </td> </tr> <!-- 移除原循环内的Partial渲染代码 --> } </table> } else { <h2 style="text-align:center">There's no one here yet. :(</h2> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addPlayer">Create</button> }
2. 在Index视图中添加模态框容器
在Index页面内容区域末尾添加空容器,用于加载Edit模态框:
<div class="container-fluid"> @await Html.PartialAsync("_PlayersTable", Model.Players) @await Html.PartialAsync("~/Views/Player/Create.cshtml", new PlayerViewModel()) <!-- 添加模态框容器 --> <div id="editPlayerModalContainer"></div> </div>
3. 添加JS代码处理AJAX加载和验证绑定
在Index视图底部或布局页中添加脚本:
$(document).ready(function() { // 绑定Edit按钮点击事件 $(document).on('click', '.edit-player-btn', function() { var playerId = $(this).data('player-id'); var modalId = '#EditPlayer-' + playerId; // AJAX请求获取Edit PartialView $.get('/Player/Edit/' + playerId, function(partialHtml) { $('#editPlayerModalContainer').html(partialHtml); $(modalId).modal('show'); // 重新初始化表单验证 var form = $(modalId).find('form'); form.removeData('validator').removeData('unobtrusiveValidation'); $.validator.unobtrusive.parse(form); }); }); // 模态框关闭后清空内容(可选) $(document).on('hidden.bs.modal', '.modal', function() { $(this).remove(); }); });
4. 确保ViewModel包含验证特性
检查PlayerViewModel的Name属性是否添加验证标记:
public class PlayerViewModel { public int Id { get; set; } [Required(ErrorMessage = "请输入玩家名称")] [StringLength(50, ErrorMessage = "名称不能超过50个字符")] public string Name { get; set; } public string Image { get; set; } // 其他属性... }
方案二:静态渲染所有Edit模态框并重新绑定验证
若要保持循环渲染Edit Partial的方式,需在页面加载完成后手动触发所有表单的验证解析:
1. 将Edit Partial渲染移至Index视图
在Index页面内容区域添加循环渲染:
<div class="container-fluid"> @await Html.PartialAsync("_PlayersTable", Model.Players) @await Html.PartialAsync("~/Views/Player/Create.cshtml", new PlayerViewModel()) <!-- 循环渲染所有Edit模态框 --> @foreach (var player in Model.Players) { @await Html.PartialAsync("~/Views/Player/Edit.cshtml", player) } </div>
2. 添加JS代码初始化所有表单验证
$(document).ready(function() { // 对页面中所有表单重新解析验证规则 $('form').each(function() { $(this).removeData('validator').removeData('unobtrusiveValidation'); $.validator.unobtrusive.parse($(this)); }); });
关键注意事项
- 确保页面已正确引用所需脚本:
jquery.min.js、jquery.validate.min.js、jquery.validate.unobtrusive.min.js、bootstrap.bundle.min.js。 - Post请求返回PartialView时,若ModelState无效,返回的表单同样需要重新绑定验证(方案一中的AJAX逻辑已处理此情况)。
内容的提问来源于stack exchange,提问作者Brunny
相关产品推荐
相关产品推荐

