【问题标题】:Page Refresh Causes Duplicate POST in ASP.NET Applications页面刷新导致 ASP.NET 应用程序中的重复 POST
【发布时间】:2009-04-13 10:43:36
【问题描述】:

我有一个应用程序,我在其中添加一条新记录,如果我按下刷新按钮,记录会被添加两次。

我正在清除缓存,但我遇到了同样的问题。 怎么办?

【问题讨论】:

  • 没有足够的信息来帮助你
  • 这个问题过去肯定被问过很多次,但我很难找到其他问题。我已经改写了标题,以便将来可以找到这个问题。我希望安妮和社区不要介意。

标签: asp.net


【解决方案1】:

一旦您处理了返回页面的帖子,最佳做法是随后重定向,这样您就无法使用“刷新”按钮再次发布数据。这对所有 Web 开发都很常见,而不仅仅是 ASP.NET。

【讨论】:

  • 但是这样做是在进行不必要的服务器访问。有没有其他方法可以避免这种情况。
  • 两害相权取其轻,我猜。
  • 仅供参考 - 避免这种情况的设计模式称为 Post/Redirect/Get 模式。
【解决方案2】:

我的方法被无耻地从this ASP Alliance 上的精彩文章的第 4 页窃取。要检测刷新,您可以在 ViewState 和 Session 中存储相同的值。如果用户刷新页面,它将使用与您的 Session 值不匹配的旧 ViewState 数据进行 PostBack。一旦检测到这一点,您就可以使用一个简单的变量创建一个所有其他 Page 都继承自的 Page,以测试用户是否刷新了浏览器。此解决方案需要启用 ViewState 和有效的 Session。

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    if (IsPostBack && ViewState[REFRESH_CHECK_GUID] != Session[REFRESH_CHECK_GUID])
    {
        IsRefresh = true;
    }
    Session[REFRESH_CHECK_GUID] = System.Guid.NewGuid().ToString();
    ViewState[REFRESH_CHECK_GUID] = Session[REFRESH_CHECK_GUID];
}

/// <summary>
/// True if the last PostBack was caused by a Page refresh.
/// </summary>
public virtual bool IsRefresh
{
    get;
    private set;
}

【讨论】:

  • 我也在应用程序中使用了该示例,基本上将 IsRefresh 作为属性添加到我的所有基本 Web 表单页面。效果很好。
【解决方案3】:

在理想情况下,导致数据库更新的 HTTP POST 提交将在成功更新后重定向到通知用户操作成功的辅助页面。如果用户试图返回上一个页面,浏览器会提示用户类似“”如果不重新发送信息,页面将无法刷新。单击“重试”重新发送信息或单击“取消”继续“。这足以说明用户刷新页面将导致重复提交。但是,如果更新失败,将加载同一页面并允许用户重试。

当然,这不是一成不变的规则,实施方式各不相同。我强烈建议您将 @edg 的建议付诸实践 - 您的数据库插入代码应始终在应用插入/更新之前检查重复性。

【讨论】:

  • 感谢您向我介绍“重复”一词。这是新词吗?
  • 我不会认为创造这个词的功劳,因为它似乎很常用 (google.com/search?q=duplicacy),即使我找不到这个词的单一定义!很好,约翰。嘿,我的选票呢?! :P
【解决方案4】:

如果您没有任何会话(并且启用了 cookie),您可以使用:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    if (IsPostBack && ViewState[REFRESH_CHECK_GUID] != Request.Cookies[REFRESH_CHECK_GUID])
    {
        IsRefresh = true;
    }
    String checkGuid=System.Guid.NewGuid().ToString();
    Response.Cookies[REFRESH_CHECK_GUID] = checkGuid;
    ViewState[REFRESH_CHECK_GUID] = checkGuid;
}

/// <summary>
/// True if the last PostBack was caused by a Page refresh.
/// </summary>
public virtual bool IsRefresh
{
    get;
    private set;
}

【讨论】:

  • 这在 SharePoint 完全信任实现中看起来是一个不错的解决方案,默认情况下使用 Session 是不可用的。
【解决方案5】:

如果应用程序是您的,您需要添加代码,在尝试将记录保存到数据库之前先检查该记录是否不存在。

【讨论】:

  • 如果我们想允许复制,那该怎么办?
  • 那你就没有问题了,我想。至少不是根据你的问题。
【解决方案6】:

问题是由于位于 __EVENTTARGET 中的隐藏值无法通过代码设置。

如果您可以使用 Ajax 添加数据,则可以解决此问题。

【讨论】:

    【解决方案7】:

    即使我们对整个表单使用 Ajax,它也会提供相同的重复插入, 但我们可以尝试通过清除 hiddenfield _EventTaret 并更改其他一些控件的焦点:)

    【讨论】:

      【解决方案8】:

      正如 David M 上面所说,最好的办法是在发布后重定向。另一个服务器往返的影响非常小,因为只有 http 标头在重定向中发送。

      【讨论】:

        【解决方案9】:

        如果您需要留在同一页面,那么我建议您将用户重定向到确认页面,然后您可以询问用户是否要插入另一条记录,如果是,那么您将它们重定向回可以插入记录的页面,这将有助于防止重复插入。或者,如果他们完成插入记录,他们可以直接进入“主”页面。当我需要用户在插入后能够“停留”在同一页面中时,这就是我过去所做的。

        【讨论】:

          【解决方案10】:

          插入或更新语句执行后,您可以将用户重定向到同一页面

          Response.Redirect(Request.Url.AbsoluteUri);

          【讨论】:

            猜你喜欢
            • 2018-02-17
            • 1970-01-01
            • 2013-02-15
            • 1970-01-01
            • 2018-01-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-30
            相关资源
            最近更新 更多