我可以看到,我自己和很多人在ASP.NET中使用这两个项目时遇到了麻烦...刷新按钮,后退按钮......(我看到很多人都去问过如何禁用这两个按钮在浏览器..)
现在在Page中实现两个更多的布尔变量有什么问题(IsRefresh,IsPostBack)......如果这些问题可以被规避和实施,那对开发者来说将是一笔巨大的资产......
当您回答时,如果您还可以在Web应用程序中包含您要采取的步骤,以避免在有用的情况下重新发布(有时在数据库中)。
由于
答案 0 :(得分:5)
实现两个额外的布尔属性的问题是,确实没有(可靠的)方法来区分 Back / Refresh 触发的请求。当点击这些按钮时,浏览器将:
您正在遇到案例#2。发生第二个请求时,服务器将收到与原始请求相同的完全相同的请求数据。因此,ASP.NET(和大多数其他框架)将处理请求,就像处理原始请求一样。有几种方法可以解决此问题:
ViewState
中的数据)。然后添加一些数据结构以保留“已使用”值的列表,以及在执行任何关键操作之前测试重复项的逻辑。POST
请求永远不会在浏览器历史记录中结束。解决方案#3简单易行,几乎适用于所有情况。基本上,而不是将结果/确认作为对“关键”回发的回复返回,请重定向到新的URL:
protected void btnCritical_Click(object sender, EventArgs e)
{
DoSomethingThatShouldNotBeDoneTwice();
Response.Redirect("confirmation.aspx");
}
答案 1 :(得分:1)
这不是那么明确。服务器识别“PostBack”的唯一方法是基于请求传递给页面的标头。当您发布表单时,“IsPostBack”是正确的,正如您所期望的那样。刷新页面或按“返回”时,将发送完全相同的请求数据。应用程序无法检测用户是否发出了非标准请求(后退或刷新)而未更改发送请求的浏览器的行为。
如您所知,大多数浏览器会向您显示“单击后退将重新发送表单数据...”,但这仅仅是浏览器发出的警告,让您知道它将发送完全相同的请求再次。服务器不知道这一点,也没有(本地)方式来解释信息。
双重预回复提示
阻止数据发布两次的一种方法是确保每个PostBack都包含一些您可以验证的唯一数据。这个过程相当简单。
在每个页面加载时,您将需要为该页面的PostBack事件创建唯一标识符。唯一ID是什么并不重要,只要它在顺序页面加载时不一样。将该唯一标识符放在页面上的隐藏字段中以及用户的会话(或cookie)中。然后,在每个PostBack上验证隐藏字段中的cookie 是否匹配会话中的值。如果值匹配,则PostBack是页面的原始帖子,可以相应地进行处理。执行必要的操作后,您需要再次更改两个位置中的唯一标识符。这样,如果用户应该回击并选择“重新发送数据”,则隐藏字段将与会话密钥不匹配,您可以丢弃重复的发布数据。
答案 2 :(得分:1)
aspnet_isapi识别来自表单内容的回发,特别是ViewState字段。它没有内在的方法来区分回发和刷新。
过去,我已经看到了一些与此相关的策略。一种方法是为每个请求分配一个guid,并将其用作您写入的表中的唯一键或索引。
您可以创建所有网页都继承的基页。
public partial class PageBase : System.Web.UI.Page
{
private Guid _requestId;
protected Guid RequestId
{
get
{
return _requestId;
}
}
protected virtual void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_requestId = Guid.NewGuid();
ViewState.Add("requestId", _requestId);
}
else
{
_requestId = (Guid)ViewState["requestId"];
}
}
}
public partial class _Default : PageBase
{
protected override void Page_Load(object sender, EventArgs e)
{
base.Page_Load(sender, e);
// now do stuff
}
}