6

我有一个带有 Form 元素 ( <form runat="server">) 的母版页、一个带有 Button 元素 ( <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Sync" />) 的内容页,以及一个包含该Button1_Click函数的 Code Behind 页面。

用户来到页面并单击按钮。代码背后的代码执行(在服务器上),它更新数据库中的一些表。Code behind 代码所做的最后一件事是InnerHTML在内容页面上设置 Span 元素的成功或失败消息。

这一切都很好。问题是如果用户刷新页面,表单被重新提交并且浏览器询问这是否真的是用户想要的。如果用户的回答是肯定的,则重新执行 Code Behind 代码并再次更新数据库。如果用户做出否定的回应,那么什么也不会发生。

重新执行代码背后的代码没什么大不了的。它不会伤害任何东西。但这并不是我想要的行为。

我知道我可以使用 Response.Redirect() 重定向回页面,但是用户永远不会看到我的成功或失败消息。我应该提到该消息实际上不仅仅是“成功”或“失败”,否则我想我可以在重定向的查询字符串中添加一些内容。

有没有办法从代码隐藏代码中重置表单元素,以便如果用户刷新页面,表单不会重新提交?

主页面...

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="IntuitSync.SiteMaster" %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:ipp="">
    <head runat="server">
    </head>
    <body>
        <form runat="server">
            <div runat="server" id="mainContetntDiv">
                <asp:ContentPlaceHolder ID="MainContent" runat="server" />
            </div>
        </form>
    </body>
</html>

内容...

<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.master" CodeBehind="SyncToCloud.aspx.cs" Inherits="IntuitSync.SyncToCloud" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Sync" />
    <span runat="server" id="SyncStatus"></span>
</asp:Content>

背后的代码...

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Web;

namespace IntuitSync
{
    public partial class SyncToCloud : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            /*
                Do a bunch of stuff and put the results in syncResults which is a List.
            */
            SyncStatus.InnerHtml = string.Join("", syncResults.ToArray()); // I'd rather do this...
            //Response.Redirect(Request.Url.PathAndQuery, true);  // ...and not do this.
        }
    }
}

非常感谢任何和所有帮助。

4

2 回答 2

8

问题是你正在做一个表单 POST,如果用户随后刷新页面,它会做它应该做的事情:重新提交 POST。没有其他办法了。因此,您可以使用的选项如下:

  1. 重定向到确认页面,以某种方式将操作结果传递给确认页面(如果查询字符串/cookie/等不可行,通常从某个数据存储库重新加载)。
  2. 重定向到同一页面,但通过查询字符串参数传递成功消息(或者愚蠢地将其存储在 session/ViewState/what-have-you-silliness 中)。
  3. 不要发布,而是获取表单,因为您似乎没有发布任何值,只是启动某种服务器端处理。为此,只需将您的表单从帖子更改为获取,或者只是做一个链接。这里的危险是您不应该在任何 get 操作中进行任何变革性/破坏性操作。

注意:确保清理所有用户输入(始终将用户输入视为邪恶)。

您可能对最后一个选项最满意,但这完全取决于“做一堆东西并将结果放入 syncResults ...”真正需要什么。

更新(多年后)

虽然这应该是显而易见的,但对某些用户来说可能不够明显:您永远不应该通过直接显示未经清理的“通过查询字符串参数的成功消息”来向 XSS 攻击敞开心扉。这些建议认为这很明显,但回想起来,这方面应该是明确的。

于 2013-02-07T22:07:33.083 回答
1

我建议进入 JASON 路线

在 SyncToCloud.aspx.cs

[System.Web.Services.WebMethod]
    public static string updateSyncStatus()
    {
        /*
                Do a bunch of stuff and put the results in syncResults which is a List.
            */
            SyncStatus.InnerHtml = string.Join("", syncResults.ToArray()); // I'd rather do this...
            //Response.Redirect(Request.Url.PathAndQuery, true);  // ...and not do this.
    }

在 SyncToCloud.aspx

function SyncStatus(){
                $.ajax({
                            type: "POST",
                            async:true,
                            url: "syncToCloud.aspx/updateSyncStatus",
                            data: <if have anydata>,
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",
                            success: function (msg) {
                                if (msg.d == "Success") {                                    
                                    //Set message on some lable or do something
                                } else {
                                    //Proceed to show message on wrong password
                                }
                            } 
                        }); 
            }

按钮上的标记

<asp:Button ID="Button1" runat="server" OnClientClick="SyncStatus(); return false;" Text="Sync" />
于 2015-07-22T03:38:39.833 回答