【问题标题】:Confirm Form Resubmission on browser popup duplicates the record在浏览器弹出窗口中确认重新提交表单会重复记录
【发布时间】:2014-10-14 19:49:53
【问题描述】:

我正在开发一个存在问题的应用程序。当我点击提交按钮时,数据被插入到数据库中。但是当我按下 ctrl+R 或 f5 时,会出现一个 chrome 或 IE 弹出窗口,上面写着 Confirm Form Resubmission。当我点击继续时,记录被复制到数据库中。

我的问题是,

  1. 为什么会出现这个弹出窗口?因为回发?如果因为回发,那么我的代码是否有任何问题,或者在回发时每个人都会发生。

  2. 使用 mvc 会彻底解决这个问题吗?

我的代码:

protected void btnSubmit_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                paramArray = new string[9];
                paramValues = new object[9];
                try
                {
                    paramArray[0] = "@AccountNumber";
                    paramValues[0] = (!string.IsNullOrEmpty(this.txtAccountNumber.Value) ? this.txtAccountNumber.Value.Trim() : string.Empty);

                    paramArray[1] = "@OpeningBalance";
                    paramValues[1] = (!string.IsNullOrEmpty(this.txtOpeningBalance.Value) ? Convert.ToDouble(this.txtOpeningBalance.Value.Trim()) : 0.00);

                    paramArray[2] = "@ClosingBalance";
                    paramValues[2] = (!string.IsNullOrEmpty(this.txtClosingBalance.Value) ? Convert.ToDouble(this.txtClosingBalance.Value.Trim()) : 0.00);

                    paramArray[3] = "@PaymentMode";
                    paramValues[3] = this.ddlModeofPayment.Value;

                    paramArray[4] = "@PaymentDate";
                    paramValues[4] = this.dtPaymentDate.Value;

                    paramArray[5] = "@PaymentAmount";
                    paramValues[5] = (!string.IsNullOrEmpty(this.txtPaymentAmount.Value) ? Convert.ToDouble(this.txtPaymentAmount.Value.Trim()) : 0.00);

                    paramArray[6] = "@isAccount";
                    paramValues[6] = true;

                    paramArray[7] = "@UserId";
                    paramValues[7] = (!string.IsNullOrEmpty(this.User.Identity.Name.Remove(0, 7)) ? this.User.Identity.Name.Remove(0, 7) : string.Empty);

                    paramArray[8] = "@isProcessed";
                    paramValues[8] = default(bool);

                    var success = herlperUtility.ExecuteParameterizedQuery("{CALL asp_sp_InsertPayment(?,?,?,?,?,?,?,?,?)}", paramArray, paramValues);

                    if (!string.IsNullOrEmpty(success.Rows[0]["ReferenceNumber"].ToString()))
                    {
                        this.Page.Response.Redirect("AccountPaymentScreen.aspx?flag=1");
                        divSuccess.Attributes.Add("style", "display:block");
                        this.refId.InnerText = "<b>Success!</b> The " + success.Rows[0]["ReferenceNumber"] + " has been successfuly forwarded to the supervisor";

                        this.ClearFields();
                    }

                    else
                    {
                        this.divFailure.Attributes.Add("style", "display:block");
                    }
                }
                catch (Exception ex)
                {
                    this.divFailure.Attributes.Add("style", "display:block");
                    this.divFailure.InnerText = ex.Message;
                }
            }

【问题讨论】:

标签: c# asp.net postback


【解决方案1】:

解决这个问题的方法是关注Post-Redirect-Get pattern。这意味着在您执行某种事务活动的 HTTP POST 之后,您将客户端重定向到 HTTP GET。

以一种非常简单的思维方式:GET 不应该修改任何内容,而 POST 可以进行更改。

例如,考虑以下工作流程。

  1. 用户在购物车页面上按下提交 (HTTP POST)。
  2. 您确认信用卡有效,如果有效,则向 帐户并启动您的仓库活动
  3. 您会显示一个确认订单的屏幕。

如果一切顺利并且您没有重定向客户端(例如,您显示带有成功消息的面板并隐藏购物车)并且客户端按下刷新,订单将重新提交,这可能不适合其他任何人比应收账款。

遵循 PRG 模式,在提交订单后,您将重定向到 GET 页面(可能在查询字符串中使用订单 ID,以便您可以通过某种方式引用订单)并显示成功消息。此页面可以根据客户的需要多次刷新(附加的好处是可添加书签),不会对您的后端系统或客户的钱包产生任何副作用。

值得注意的是,您不必对此感到狂热。在此示例中,如果信用卡验证失败,您可以选择仅显示 POST 操作的结果并在页面上切换错误消息。如果用户刷新页面,验证将运行并再次失败,但不会对您的后端系统进行任何更改。

至于 MVC - 并不是说​​它更容易实现(确实如此),而是您最终会比使用 WebForms 时更多地考虑这些事情,因为 WebForms(无论好坏)隐藏了这些概念抽象的背后。

【讨论】:

  • 这不是解决方案,而是规避。企业不要求这种类型的拼凑,他们想要直接的帖子。令人惊讶的是,浏览器之王认为他们不得不假设开发人员不知道如何完成他们的工作。
  • 如果我误解了您,我深表歉意,但我不明白这不是解决方案吗?浏览器显示作为 POST 命令的结果返回的 html,并假设如果您点击刷新,您要求执行完全相同的操作。没有人说不做直接的 POST,而是说该操作完成后要做什么。 Post-Redirect-Get 是一种众所周知的处理模式。
  • 好的,谢谢乔,不用担心,我只是从程序员的角度来看这个,假设第一篇文章确实完成了。任何插入 DB 的东西都应该有一个唯一 ID,应该作为确认的一部分返回。如果帖子发生了两次,并且有确认,那么程序应该什么都不做。这就是我要说的……当浏览器决定什么是最好的时,我们最终会在开发时点击废话。海事组织...
  • 实际上,如果将帖子提交到数据库,则在重置浏览器状态之前不应向用户显示表单。 PRG 是 IMO 对糟糕设计的一种规避,但也许不是,请解释一下。
猜你喜欢
  • 1970-01-01
  • 2015-07-01
  • 2018-04-19
  • 2015-01-14
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多