Page_ClientValidate致无关LinkButton需双击回发的问题排查
TL;DR:未选中ListBox项点击Edit触发客户端验证失败后,Delete按钮(LinkButton)首次点击无响应,本质是ASP.NET客户端验证框架的状态残留导致表单
onsubmit事件返回false,阻止了首次__doPostBack的提交;第二次点击时状态重置,才正常执行。
问题场景回顾
你搭建的页面里有三个操作入口:
- New:普通HyperLink,直接跳转不触发验证
- Edit:点击时先通过
Page_ClientValidate("mustSelect")检查ListBox是否选中,验证通过才跳转编辑页 - Delete:LinkButton,触发ASP.NET自动生成的
__doPostBack提交表单
操作步骤触发的异常:
- 页面加载后未选中ListBox项
- 点击Edit,触发RequiredFieldValidator验证失败,显示错误提示
- 首次点击Delete毫无反应,第二次点击才成功触发服务器端重定向
根源分析
你找到的__doPostBack代码是关键:
function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } }
当你手动调用Page_ClientValidate("mustSelect")且验证失败时,ASP.NET的客户端验证框架会设置内部标记Page_BlockSubmit = true,同时表单的onsubmit事件会关联验证逻辑——此时首次点击Delete(触发__doPostBack)时,theForm.onsubmit()会返回false,直接跳过表单提交逻辑;第二次点击时,验证框架会重新检查(而Delete不属于任何验证组),Page_BlockSubmit被重置为false,onsubmit()返回true,才会执行提交。
另外注意你原JS代码里的一个小错误:parseInt(i) != NaN永远为false(因为NaN和任何值比较都是false),应该改成!isNaN(parseInt(i))。
修复方案
这里给你两种简单有效的解决办法:
方案1:给Delete按钮设置空的ValidationGroup
既然Delete不需要任何验证,直接给LinkButton指定空的ValidationGroup属性,这样ASP.NET会知道这个按钮触发提交时跳过所有验证组的检查:
<asp:LinkButton ID="lnk_delete" runat="server" Text="Delete" ValidationGroup="" />
这个方法最简洁,不需要修改JS代码,就能让Delete按钮在任何情况下首次点击就触发提交。
方案2:手动重置验证状态(适合需要保留原逻辑的场景)
在Edit的点击函数里,验证失败后手动重置验证框架的状态,避免残留的验证失败标记影响后续操作:
function RedirectToPageWithSelectedId() { if (Page_ClientValidate("mustSelect")) { var li = $("#<%=ListBox1.ClientID%> option:selected"); var i = li.val(); if (!isNaN(parseInt(i))) { window.location.href = "/edit/" + i; } } else { // 重置阻止提交的标记 Page_BlockSubmit = false; // 可选:清除该验证组的错误显示状态 for (var idx = 0; idx < Page_Validators.length; idx++) { var validator = Page_Validators[idx]; if (validator.validationGroup === "mustSelect") { ValidatorEnable(validator, true); ValidatorUpdateDisplay(validator); } } } }
验证效果
无论是哪种方案,测试后都能解决“Delete首次点击无响应”的问题:
- 未选ListBox点击Edit触发验证失败后,首次点击Delete就能直接触发服务器端重定向
- 不影响Edit按钮的原有验证逻辑
内容的提问来源于stack exchange,提问作者EvilDr

