【问题标题】:How can I ignore an http request without clearing the browser?如何在不清除浏览器的情况下忽略 http 请求?
【发布时间】:2010-03-24 20:37:53
【问题描述】:

为了防止重复请求(即在单击命令按钮后立即按 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() 立即结束任务。这使用户的浏览器为空。

有没有办法让用户保持原样,以便他们只需单击一个按钮?

还有;请注意,这段代码是我能想出的最简单的代码来演示我的问题。这并不是为了演示如何检查 dup 请求。

编辑:另一个可以让我获得相同结果的更改是禁用我的所有事件处理程序。这可能吗?

【问题讨论】:

    标签: asp.net webforms postback duplicates


    【解决方案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;
            }
        }
    }
    

    【讨论】:

    • 这将允许我阻止事件执行。谢谢。
    【解决方案2】:

    不要强制结束响应。让它优雅地结束(失败),而无需通过您的“主要”逻辑来处理合法请求。如果这证明工作量太大,那么您的代码可能需要重构。或者,懒惰的方法是,您可以设置一个全局布尔值来指示请求的有效性(在您的 Page_Load 中设置),然后根据需要在其余代码中检查它。

    编辑

    我对此思考得越多,我就越倾向于采用更用户友好的方法。与其结束请求,不如将他们重定向到一个专门用于告知他们如何避免站点中出现重复请求的页面?这就是我的银行网站所做的。

    【讨论】:

    • 我可以从每个事件处理程序中检查,但想要一种方法从基类中尽可能不干扰地执行此操作。我正在考虑关闭所有事件处理程序,但我不确定是否可以这样做......可以吗?
    • "与其结束请求,不如将他们重定向到一个专门用于告知他们如何避免站点中重复请求的页面?"试图告诉你的用户如何使用他们的浏览器是网页应用设计的一大罪过。
    • @Frank 谁说过“告诉用户如何使用他们的浏览器”?告诉他们如何有效地使用您的网站。我知道你来自哪里,但这不是一个完美的世界,每条规则都有例外。
    【解决方案3】:

    查看发送 HTTP 响应代码 204 No Content 是否符合您的要求。

    【讨论】:

      猜你喜欢
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      相关资源
      最近更新 更多