TL; DR:如果单击“编辑”按钮而没有选择列表框,触发验证失败,为什么需要点击{strong>两次1}链接Delete
链接>在浏览器响应之前?
使用下面的源代码获得一个非常简单的菜单,我有三个链接:
New
- 不执行验证并重定向到"创建"形式Edit
- 检查是否已选择ListItem,如果是,则重定向到"编辑"具有作为参数提供的ID值的表单Delete
- 重定向到"删除"页面,无论是否进行选择我注意到一种奇怪的行为,并在这个简单的单页解决方案(download link from OneDrive)中重现:
Edit
而不从列表框中进行选择(出现验证错误)Delete
- 没有任何反应 - 为什么?Delete
- 服务器端重定向成功发生,但这应该发生在上面的第3步以下是我的浏览器中发生的情况(在Chrome,FF和Edge中测试过) - 请注意,删除链接需要两次点击:
问题似乎出现在ASP.Net的表单提交代码中:
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
// On first click - this logic path is never reach, but on the second click, it is reached
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
在我手动调用if
之后,我试图找出Page_ClientValidate()
语句返回false的原因。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Test Page</title>
<script>
function RedirectToPageWithSelectedId() {
if (Page_ClientValidate("mustSelect")) { // Asp.Net client-side validation, passing ValidationGroup as parameter
var li = $("#<%=ListBox1.ClientID%> option:selected");
var i = li.val();
if (parseInt(i) != NaN) {
window.location.href = "/edit/" + i;
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:ListBox ID="ListBox1" runat="server" />
<asp:RequiredFieldValidator ID="Rfv1" runat="server" Text="Selection required" ValidationGroup="mustSelect" ControlToValidate="ListBox1" Display="Dynamic" />
</p>
<ul>
<li>
<asp:HyperLink ID="lnk_new" runat="server" Text="New" NavigateUrl="~/new" />
</li>
<li>
<asp:HyperLink ID="lnk_edit" runat="server" Text="Edit Selected" onclick="RedirectToPageWithSelectedId(); return false;" href="#" />
</li>
<li>
<asp:LinkButton ID="lnk_delete" runat="server" Text="Delete" />
</li>
</ul>
</div>
</form>
</body>
</html>
如果需要,我可以更新以提供页面代码隐藏;只是问。
答案 0 :(得分:1)
我会做这样的事情。给包含元素的<div>
一个类名,并按类绑定lnk_edit
的单击。现在,您可以找到是否选择了元素而无需使用ClientID
。这也可以根据需要使用尽可能多的myContainer
个副本,而无需添加更多jQuery代码。
<div class="myContainer">
<p>
<asp:ListBox ID="ListBox1" runat="server" />
</p>
<ul>
<li>
<asp:HyperLink ID="lnk_new" runat="server" Text="New" NavigateUrl="~/new" />
</li>
<li>
<asp:HyperLink ID="lnk_edit" runat="server" Text="Edit Selected" href="#" CssClass="myEditLink" />
<span class="myEditLinkWarning"></span>
</li>
<li>
<asp:LinkButton ID="lnk_delete" runat="server" Text="Delete" />
</li>
</ul>
</div>
<script type="text/javascript">
$('.myContainer .myEditLink').click(function () {
$(this).closest('div').find('select option').each(function () {
if ($(this).prop('selected')) {
window.location.href = "/edit/" + $(this).val();
}
});
$(this).closest('div').find('.myEditLinkWarning').html('Please select');
});
</script>
答案 1 :(得分:0)
在使用Chrome的调试器进行了大量调查之后,我找到了以下逻辑和解决方法。如果我弄错了,或者是否有更好的方法与客户端的ASP.Net验证控件进行交互,请告诉我?
单击LinkButton时,ASP.Net将通过其验证逻辑工作,即使该控件未导致验证。这是让我感到惊讶的第一件事。在处理验证逻辑之前,实际上不会提交表单。
在验证过程中,有两个页面级变量被设置:
<强> Page_IsValid
强>
这是一个总体布尔值,表示所有验证器都有效。
<强> Page_BlockSubmit
强>
这通常保持Page_IsValid
的相反值,并阻止表单提交true
。
点击我的Edit
链接后,我的代码针对特定验证组启动了客户端验证:
Page_ClientValidate("mustSelect");
在该方法中,Page_IsValid
变为false
,因此Page_BlockSubmit
变为true
。这可以防止表单在显示验证错误后执行任何操作,并且是预期的。
LinkButton的点击事件引发了问题。按下时,无论LinkButton是否正在执行验证,都会执行以下JavaScript:
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
// This is never reached if Page_BlockSubmit = true
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
最后一个验证结果仍保留在浏览器中,因此Page_BlockSubmit
仍为true
。这导致上述方法跳过提交表单的内部代码,这意味着表单永远不会被提交。
奇怪的是,在方法完成后,Page_IsValid
和Page_BlockSubmit
都会重置为默认值。这就是页面提交第二次编辑点击。
这感觉就像一个完整的黑客,但是当单击LinkButton时强制Page_BlockSubmit
的值为false,一切都按预期工作,并且不需要手动开始重置validation.isvalid
属性,或隐藏消息。所有其他验证组/逻辑继续正常工作,但编辑链接现在可以按用户期望的那样工作:
<asp:LinkButton ID="lnk_delete" runat="server" Text="Delete" OnClientClick="Page_BlockSubmit = false;" />
同样,我不知道是否会破坏ASP.Net的任何工作方式,并且不胜感激。