防止在 ASP.Net 中重新送出表單(不重定向到我自己)
我有一個帶有 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. } } }非常感謝任何和所有幫助。
問題是你正在做一個表單 POST,如果使用者隨後刷新頁面,它會做它應該做的事情:重新送出 POST。沒有其他辦法了。因此,您可以使用的選項如下:
- 重定向到確認頁面,以某種方式將操作結果傳遞給確認頁面(如果查詢字元串/cookie/等不可行,通常從某個數據儲存庫重新載入)。
- 重定向到同一頁面,但通過查詢字元串參數傳遞成功消息(或者愚蠢地將其儲存在 session/ViewState/what-have-you-silliness 中)。
- 不要發布,而是做一個表單,因為看起來您沒有發布任何值,只是啟動某種伺服器端處理。為此,只需將您的表單從文章更改為獲取,或者只是做一個連結。這裡的危險是您不應該在任何 get 操作中進行任何變革性/破壞性操作。
注意:確保清理所有使用者輸入(始終將使用者輸入視為邪惡)。
您可能對最後一個選項最滿意,但這完全取決於“做一堆東西並將結果放入 syncResults …”真正需要什麼。
更新(多年後)
雖然這應該是顯而易見的,但對某些使用者來說可能還不夠明顯:您永遠不應該通過直接顯示未經清理的“通過查詢字元串參數的成功消息”來向 XSS 攻擊敞開心扉。這些建議認為這很明顯,但回想起來,這方面應該是明確的。