为了防止重复请求(即在单击命令按钮后立即按F5),我设置了我的页面基类,如果它被检测为重复请求,则忽略该请求。
当我说'忽略'时,我指的是Response.End()
现在我以为我之前看过这个工作,哪里有问题,我只是Response.End()而用户页面什么也没做。我不知道这种情况的确切情况,但我现在无法重复。
现在当我调用Response.End()时,我只得到一个空的浏览器。更具体地说,我得到了这个HTML。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=utf-8"></HEAD>
<BODY></BODY></HTML>
我设置了以下测试应用以确认问题不在我的应用中。这是:
将以下内容添加到aspx表单
<asp:Label ID="lbl" Text="0" runat="server" /><br />
<asp:Button ID="btnAdd1" Text="Add 1" runat="server" /><br />
<asp:Button ID="btnAdd2" Text="Add 2" runat="server" /><br />
<asp:Button ID="btnAdd3" Text="Add 3" runat="server" /><br />
这是文件背后的代码
using System;
namespace TestDupRequestCancellation
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
btnAdd1.Click += btnAdd1_Click;
btnAdd2.Click += btnAdd2_Click;
btnAdd3.Click += btnAdd3_Click;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
CurrentValue = 0;
else if (Int32.Parse(lbl.Text) != CurrentValue)
Response.End();
}
protected void Page_PreRender(object sender, EventArgs e)
{
lbl.Text = CurrentValue.ToString();
}
protected int CurrentValue
{
get
{
return Int32.Parse(Session["CurrentValue"].ToString());
}
set
{
Session["CurrentValue"] = value.ToString();
}
}
void btnAdd3_Click(object sender, EventArgs e)
{
CurrentValue += 3;
}
void btnAdd2_Click(object sender, EventArgs e)
{
CurrentValue += 2;
}
void btnAdd1_Click(object sender, EventArgs e)
{
CurrentValue += 1;
}
}
}
当您加载页面时,单击任何按钮会执行预期的操作,但如果您在按下其中一个按钮后随时按F5,它会将其检测为重复请求并调用Response.End()并立即结束任务。这使用户留下了空的浏览器。
有没有让用户保持页面不变,所以他们只需点击一个按钮就可以了?
也;请注意,此代码是我可以提出的最简单的代码来演示我的问题。它并不意味着演示如何检查重复请求。
编辑:允许我获得相同结果的另一个变化是禁用我的所有事件处理程序。这可能吗?答案 0 :(得分:1)
如果您在执行事件之前检查验证器,那么挂钩验证功能可能是实现此目的最不引人注目的方法。
试试这个:
using System;
using System.Web.UI.WebControls;
namespace TestDupRequestCancellation
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
btnAdd1.Click += btnAdd1_Click;
btnAdd2.Click += btnAdd2_Click;
btnAdd3.Click += btnAdd3_Click;
AddFirstPostbackValidator();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
CurrentValue = 0;
}
protected void Page_PreRender(object sender, EventArgs e)
{
lbl.Text = CurrentValue.ToString();
}
protected int CurrentValue
{
get
{
return Int32.Parse(Session["CurrentValue"].ToString());
}
set
{
Session["CurrentValue"] = value.ToString();
}
}
private void AddFirstPostbackValidator()
{
CustomValidator val = new CustomValidator();
val.ID = "DuplicatePostbackValidator";
val.ErrorMessage = "Browser refresh detected. Command ignored.";
val.ServerValidate += val_ServerValidate;
Validators.Add(val);
form1.Controls.AddAt(form1.Controls.IndexOf(lbl) + 1, val); // user feedback
}
void val_ServerValidate(object source, ServerValidateEventArgs args)
{
args.IsValid = Int32.Parse(lbl.Text) == CurrentValue;
}
void btnAdd3_Click(object sender, EventArgs e)
{
if (!IsValid)
return;
CurrentValue += 3;
}
void btnAdd2_Click(object sender, EventArgs e)
{
if (!IsValid)
return;
CurrentValue += 2;
}
void btnAdd1_Click(object sender, EventArgs e)
{
if (!IsValid)
return;
CurrentValue += 1;
}
}
}
答案 1 :(得分:0)
不要强制响应结束。让它优雅地结束(通过),而不通过合法请求的“主”逻辑。如果这被证明是太多的工作,那么你的代码可能需要重构。或者,懒惰的方式,您可以设置一个全局布尔值,指示请求的有效性(在Page_Load中设置),然后根据需要在整个代码中检查它。
修改强>
我越是想到这一点,我更倾向于采用更加用户友好的方法。如何将它们重定向到专用于告知它们如何避免站点中重复请求的页面,而不是结束请求?这是我的银行网站所做的。
答案 2 :(得分:0)
查看发送HTTP响应代码204 No Content是否符合您的要求。