首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 返回上一頁最佳實踐:UrlReferrer + ViewState 避坑指南

     編輯:ASP.NET 基礎

前言

「返回上一頁」看似簡單,實則暗藏 Request.UrlReferrer 為 null、回發丟失、AJAX 導航不更新等坑。本文對比 Request.UrlReferrer、ViewState、Session、JS history.back() 四種方案,給出生產環境最佳實踐代碼。

方案對比

方案優點缺點適用場景
JS history.back()無服務端狀態、最快無法跨域、新標籤頁失效、無法攜帶參數純前端導航、模態框關閉
Request.UrlReferrer無需額外存儲易為 null (HTTPS→HTTP、書簽訪問、爬蟲、隱私模式)簡單鏈接跳轉、非關鍵業務
ViewState 保存 UrlReferrer頁面級隔離、回發不丟失頁面關閉即失效、ViewState 增大詳情頁返回列表頁 (推薦)
Session 存儲返回地址跨頁面持久化多標籤頁污染、需手動清理多步向導、跨模塊跳轉

最佳實踐:ViewState + UrlReferrer (詳情頁 → 列表頁)

1. 頁面加載時捕獲並保存

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // 關鍵:只在首次加載捕獲,回發時保持 ViewState 原值
        if (Request.UrlReferrer != null)
        {
            ViewState["ReturnUrl"] = Request.UrlReferrer.ToString();
        }
        else
        {
            ViewState["ReturnUrl"] = ResolveUrl("~/Default.aspx"); // 兜底首頁
        }
    }
}

2. 返回按鈕點擊事件

protected void btnReturn_Click(object sender, EventArgs e)
{
    string returnUrl = ViewState["ReturnUrl"]?.ToString() ?? ResolveUrl("~/Default.aspx");
    Response.Redirect(returnUrl);
}

3. 列表頁鏈接跳轉詳情頁 (保留返回地址)

<asp:HyperLink ID="hlDetail" runat="server" 
    NavigateUrl='<%# "Detail.aspx?id=" + Eval("Id") + "&returnUrl=" + Server.UrlEncode(Request.RawUrl) %>'>
    查看詳情
</asp:HyperLink>

4. 詳情頁優先使用查詢字符串參數

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        string returnUrl = Request.QueryString["returnUrl"];
        if (!string.IsNullOrEmpty(returnUrl))
        {
            ViewState["ReturnUrl"] = returnUrl; // 最高優先級:列表頁傳遞
        }
        else if (Request.UrlReferrer != null)
        {
            ViewState["ReturnUrl"] = Request.UrlReferrer.ToString(); // 次優先:瀏覽器Referrer
        }
        else
        {
            ViewState["ReturnUrl"] = ResolveUrl("~/Default.aspx"); // 兜底
        }
    }
}

進階:基類封裝通用返回邏輯


public class BasePage : System.Web.UI.Page
{
    protected string ReturnUrl
    {
        get => ViewState["ReturnUrl"]?.ToString() ?? ResolveUrl("~/");
        set => ViewState["ReturnUrl"] = value;
    }
    
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!IsPostBack)
        {
            // 優先級:QueryString > UrlReferrer > Default
            ReturnUrl = Request.QueryString["returnUrl"] 
                     ?? (Request.UrlReferrer?.ToString()) 
                     ?? ResolveUrl("~/");
        }
    }
    
    protected void RedirectBack() => Response.Redirect(ReturnUrl);
}

避坑檢查清單

  • ✅ 首次加載捕獲:`!IsPostBack` 內賦值,否則回發覆蓋
  • ✅ 兜底地址:Referrer 為 null 時導向首頁/列表頁
  • ✅ 列表頁主動傳參:`returnUrl=Request.RawUrl` 解決 HTTPS→HTTP、書簽訪問 Referrer 丟失
  • ✅ 編碼處理:`Server.UrlEncode` 防止特殊字符截斷
  • ✅ 安全驗證:重定向前驗證 URL 是否屬於本站 (防開放重定向攻擊)

安全驗證擴展方法


public static bool IsLocalUrl(this string url, HttpRequest request)
{
    if (string.IsNullOrEmpty(url)) return false;
    if (url.StartsWith("/")) return true; // 相對路徑
    Uri absolute;
    return Uri.TryCreate(url, UriKind.Absolute, out absolute) 
        && absolute.Host.Equals(request.Url.Host, StringComparison.OrdinalIgnoreCase);
}

// 使用
if (ReturnUrl.IsLocalUrl(Request)) Response.Redirect(ReturnUrl);
else Response.Redirect("~/");

總結

「返回上一頁」核心是可靠捕獲來源地址與跨回發持久化。ViewState + QueryString參數 + UrlReferrer兜底 三層防護,覆蓋 99% 業務場景。封裝至基類 `BasePage`,全項目統一調用 `RedirectBack()`,消除重複代碼與邏輯漏洞。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved