页面刷新再次触发事件

Par*_*ras 6 asp.net page-refresh

在asp.net中,当我提交表单并刷新它时,数据又重新提交了吗?在C#中有一种方法可以在页面加载时捕获页面刷新事件吗?

Ars*_*nko 7

ASP.NET没有提供直接执行此操作的方法.

另一方面,有一些技术可以避免重复提交:

  1. 提交后重定向.这是最糟糕的一个.即使它避免重复提交,从用户的角度来看,在现代Web应用程序中也是不可接受的.

  2. 每个会话跟踪每个表单的提交.当用户第一次提交表单时,请在会话中记住这一点.如果发生了另一次提交,请尝试确定是否必须丢弃它(在某些情况下,它必须不被丢弃;例如,如果我在StackOverflow上编辑一次答案,如果需要,我将能够执行两次).

  3. 首次提交后,使用JavaScript禁用提交.这避免了在某些情况下用户双击提交按钮或第一次单击它的情况,等待并认为表单未提交,因此第二次单击.当然,不要依赖于这个:JavaScript可能被禁用,它将在双击但不在F5刷新上工作,并且在所有情况下该技术都不是完全可靠的.

举个例子,让我们尝试实现第二个.

假设我们有一个评论框this.textBoxComment,让用户在博客页面上添加新评论.提交是这样完成的:

private void Page_Load(object sender, System.EventArgs e)
{
    if (this.IsPostBack)
    {
        string comment = this.ValidateCommentInput(this.textBoxComment.Text);
        if (comment != null)
        {
            this.databaseContext.AddComment(comment);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果用户点击两次,则评论将发布两次.

现在,让我们添加一些会话跟踪:

private void Page_Load(object sender, System.EventArgs e)
{
    if (this.IsPostBack)
    {
        if (this.Session["commentAdded"] == null)
        {
            string comment = this.ValidateCommentInput(this.textBoxComment.Text);
            if (comment != null)
            {
                this.databaseContext.AddComment(comment);
                this.Session.Add("commentAdded", true);
            }
        }
        else
        {
            // TODO: Inform the user that the comment cannot be submitted
            // several times.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,用户只能提交一次评论.其他所有评论都将被自动删除.

问题是用户可能想要向几个博客帖子添加评论.我们有两种可能的方法来实现这一点.最简单的方法是在每个非回发请求上重置会话变量,但是这将允许用户在一个页面上提交帖子,加载另一个页面,而不是在第一个页面上点击刷新,从而提交注释两次但不是能够再在第二页上添加评论.

private void Page_Load(object sender, System.EventArgs e)
{
    if (this.IsPostBack)
    {
        if (this.Session["commentAdded"] == null)
        {
            string comment = this.ValidateCommentInput(this.textBoxComment.Text);
            if (comment != null)
            {
                this.databaseContext.AddComment(comment);
                this.Session.Add("commentAdded", true);
            }
        }
        else
        {
            // TODO: Inform the user that the comment cannot be submitted
            // several times.
        }
    }
    else
    {
        this.Session.Remove("commentAdded");
    }
}
Run Code Online (Sandbox Code Playgroud)

更高级的是在会话中跟踪提交评论的页面列表.

private void Page_Load(object sender, System.EventArgs e)
{
    List<string> commentsTrack = this.Session["commentAdded"] as List<string>;
    string blogPostId = this.ValidatePostId(this.Request.QueryString["id"]);
    if (blogPostId != null)
    {
        if (this.IsPostBack)
        {
            this.AddComment(commentsTrack);
        }
        else
        {
            if (commentsTrack != null && commentsTrack.Contains(blogPostId))
            {
                commentsTrack.Remove(blogPostId);
            }
        }
    }
}

private void AddComment(List<string> commentsTrack)
{
    if (commentsTrack == null || !commentsTrack.Contains(blogPostId))
    {
        string comment = this.ValidateCommentInput(this.textBoxComment.Text);
        if (comment != null)
        {
            this.databaseContext.AddComment(comment);
            if (commentsTrack == null)
            {
                commentsTrack = new List<string>();
            }

            commentsTrack.Add(blogPostId);
            this.Session["commentAdded"] = commentsTrack;
        }
    }
    else
    {
        // TODO: Inform the user that the comment cannot be submitted
        // several times.
    }
}
Run Code Online (Sandbox Code Playgroud)