在 Web Forms 開發中,後端處理完商業邏輯 (如新增/刪除資料) 後,常需觸發瀏覽器重新整理以顯示最新狀態。以下四種方法各有優缺點,請根據是否需保留表單資料、是否為 AJAX 回呼、使用者體驗要求 選擇。
| 方法 | 核心代碼 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|---|
| 1. Response.Redirect | Response.Redirect(Request.Url.ToString()); |
一般同步 PostBack,需完整重新載入頁面 | 語意清晰、瀏覽器歷史紀錄正確、觸發完整 Page Life Cycle | 會發出 302 導向、雙倍請求、失去 POST 資料、若在 UpdatePanel 內會報錯 |
| 2. ClientScript 註冊 location.href | ClientScript.RegisterStartupScript(this.GetType(), "reload", "window.location.href=window.location.href;", true); |
需在同一 URL 重新載入、保留查詢字串 | 可在 UpdatePanel 非同步回呼中使用、可攜帶參數 | 需注意腳本註冊時機、若重複註冊會執行多次 |
| 3. Response.AddHeader Refresh | Response.AddHeader("Refresh", "0"); |
極簡單頁面、無 AJAX、不介意 HTTP 標頭重導 | 代碼最少、無需 JS | 非標準行為、部分瀏覽器/Proxy 可能忽略、無法控制導向目標 |
| 4. ClientScript 註冊 location.reload() | ClientScript.RegisterStartupScript(this.GetType(), "reload", "window.location.reload();", true); |
需強制從伺服器重新取得 (不走快取)、AJAX 回呼 | 相當於使用者按 F5、POST 資料會重新提交 (瀏覽器會詢問) | POST 重送風險、體驗較差、UpdatePanel 需用 ScriptManager.RegisterStartupScript |
using System;
using System.Web.UI;
public static class PageRefreshHelper
{
/// <summary> 標準同步 PostBack 重導向 (推薦) </summary>
public static void RedirectToSelf(Page page, bool endResponse = false)
{
page.Response.Redirect(page.Request.RawUrl, endResponse);
}
/// <summary> 非同步回呼 (UpdatePanel) 專用:註冊 JS 重新整理 </summary>
public static void RegisterReloadScript(Page page, string key = "pageReload", bool forceServer = false)
{
string script = forceServer
? "window.location.reload(true);"
: "window.location.href = window.location.href;";
ScriptManager sm = ScriptManager.GetCurrent(page);
if (sm != null && sm.IsInAsyncPostBack)
{
ScriptManager.RegisterStartupScript(page, page.GetType(), key, script, true);
}
else
{
page.ClientScript.RegisterStartupScript(page.GetType(), key, script, true);
}
}
/// <summary> 非同步回呼專用:導向指定 URL </summary>
public static void RegisterRedirectScript(Page page, string url, string key = "pageRedirect")
{
string script = $"window.location.href = '{ResolveUrl(page, url)}';";
ScriptManager sm = ScriptManager.GetCurrent(page);
if (sm != null && sm.IsInAsyncPostBack)
ScriptManager.RegisterStartupScript(page, page.GetType(), key, script, true);
else
page.ClientScript.RegisterStartupScript(page.GetType(), key, script, true);
}
private static string ResolveUrl(Page page, string url)
{
return page.ResolveClientUrl(url);
}
}
public partial class UserList : System.Web.UI.Page
{
protected void btnDelete_Click(object sender, EventArgs e)
{
// 1. 執行刪除邏輯
int userId = Convert.ToInt32(((Button)sender).CommandArgument);
UserService.Delete(userId);
// 2. 根據頁面架構選擇重新整理方式
if (ScriptManager.GetCurrent(this)?.IsInAsyncPostBack == true)
{
// 在 UpdatePanel 內:註冊 JS 重載
PageRefreshHelper.RegisterReloadScript(this);
}
else
{
// 一般 PostBack:標準 Redirect (PRG 模式防重複提交)
PageRefreshHelper.RedirectToSelf(this);
}
}
protected void btnAjaxSave_Click(object sender, EventArgs e)
{
// 純 AJAX (非 UpdatePanel) 回呼:回傳 JSON 讓前端決定
// 後端不直接重導,改回傳 { success: true, redirectUrl: "..." }
Response.ContentType = "application/json";
Response.Write("{\"success\":true,\"redirectUrl\":\"" + Request.RawUrl + "\"}");
Response.End();
}
}
為防止使用者重新整理導致重複提交 (如重複下單),所有會修改資料的 POST 操作 應採用 PRG 模式:
// 正確 PRG 範例
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
OrderService.Create(GetOrderFromForm());
// 導向列表頁或同頁 GET,攜帶成功訊息於 TempData/Session
Response.Redirect("OrderList.aspx?msg=created", false);
Context.ApplicationInstance.CompleteRequest();
}
}
Sys.WebForms.PageRequestManagerParserErrorException。解法:改用 ScriptManager.RegisterStartupScript 註冊 window.location.href。setTimeout。location.href = location.href。若專案採用 Web API + SPA (Vue/React/Angular) 或 Blazor:
router.go(0)、queryClient.invalidateQueries()、location.reload() 或單純更新局部狀態。四種方法中,Response.Redirect (PRG 模式) 為最標準、最安全的同步做法;ScriptManager.RegisterStartupScript + location.href 為 UpdatePanel 非同步情境的正解。避免使用 Response.AddHeader("Refresh") 及直接 Response.Write 輸出腳本。新專案建議走向前後端分離,由前端掌控導航與狀態更新。