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

ASP.NET URL Rewrite 核心機制深度解析:HttpContext.RewritePath、ASP.NET Pipeline、IIS 6/7 整合模式

     編輯:ASP.NET 基礎

核心概念:URL Rewrite 發生在何處?

ASP.NET 中的 URL Rewrite 本質是在 ASP.NET Pipeline 的早期階段,透過 HttpContext.RewritePath() 修改內部請求路徑,使後續處理邏輯 (授權、Handler 選擇、頁面執行) 看到的是「重寫後」的 URL,而瀏覽器地址列保持原樣。

IIS 6 / ASP.NET Pipeline 請求流程

  1. IIS 接收 HTTP Request
  2. ISAPI 篩選器選擇 aspnet_isapi.dll 處理
  3. ASP.NET Runtime 初始化:建立 HttpContext、HttpRequest、HttpResponse
  4. 觸發 Pipeline 事件 (依序):
BeginRequest → AuthenticateRequest → AuthorizeRequest → 
ResolveRequestCache → AcquireRequestState → PreRequestHandlerExecute → 
Handler 執行 (Page/Handler/Service) →
PostRequestHandlerExecute → ReleaseRequestState → 
UpdateRequestCache → EndRequest → PreSendRequestHeaders → PreSendRequestContent

最佳實踐:在 BeginRequest 重寫

原因:BeginRequest 是 Pipeline 第一個事件,此時重寫路徑可影響所有後續事件 (授權判斷、快取鍵值、Handler 映射)。

Global.asax 實作範例

public class Global : HttpApplication
{
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;
        string rawPath = context.Request.Path; // 原始路徑 (不含查詢字串)

        // 範例 1: 靜態映射 /Customers → /CustomerList.aspx
        if (string.Equals(rawPath, "/Customers", StringComparison.OrdinalIgnoreCase))
        {
            context.RewritePath("~/CustomerList.aspx");
            return;
        }

        // 範例 2: 規則式重寫 /Product/123 → /ProductDetail.aspx?id=123
        var match = Regex.Match(rawPath, @"^/Product/(\d+)$", RegexOptions.IgnoreCase);
        if (match.Success)
        {
            string newPath = $"~/ProductDetail.aspx?id={match.Groups[1].Value}";
            context.RewritePath(newPath);
            return;
        }

        // 範例 3: 副檔名隱藏 /about → /about.aspx
        if (!rawPath.Contains(".") && !rawPath.EndsWith("/"))
        {
            string aspxPath = rawPath + ".aspx";
            if (FileExists(Server.MapPath(aspxPath)))
                context.RewritePath(aspxPath);
        }
    }

    private bool FileExists(string physicalPath)
    {
        return System.IO.File.Exists(physicalPath);
    }
}

RewritePath 內部行為詳解

public void RewritePath(string path, bool rebaseClientPath)
{
    // 1. 更新 HttpRequest 內部路徑屬性
    _request.Path = path;
    _request.FilePath = path;
    _request.PathInfo = "";
    
    // 2. 重新計算衍生屬性
    _request.PhysicalPath = MapPath(path);
    _request.QueryString = ParseQueryString(path); // 若 path 含 ?
    
    // 3. 重新解析 Handler (關鍵!)
    // 此步驟在 PreRequestHandlerExecute 事件前自動觸發
}

關鍵屬性變化對照

屬性重寫前重寫後 (/CustomerList.aspx)說明
Request.Path/Customers/CustomerList.aspx內部邏輯見到的路徑
Request.RawUrl/Customers/Customers**不變** - 瀏覽器原始 URL
Request.FilePath/Customers/CustomerList.aspx實體檔案路徑
Request.PathInfo/Customers空字串重置
Request.PhysicalPathC:\Web\CustomersC:\Web\CustomerList.aspx對應實體檔案

IIS 7 整合模式 關鍵差異

🔄 IIS 7+ 整合管線模式

  • ASP.NET Pipeline 與 IIS 原生管線融合,Managed 模組可處理靜態檔案、PHP、Python 等所有請求
  • Global.asax 事件仍適用,但建議改用 IHttpModule 或 Middleware (OWIN/ASP.NET Core)
  • Web.config 設定模組:
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true">
        <add name="UrlRewriteModule" type="MyApp.UrlRewriteModule" />
      </modules>
    </system.webServer>
  • URL Rewrite 官方模組 (Microsoft.Web.UrlRewrite) 提供 XML 規則引擎,無需寫代碼:
    <rewrite>
      <rules>
        <rule name="ProductDetail" stopProcessing="true">
          <match url="^product/([0-9]+)$" />
          <action type="Rewrite" url="ProductDetail.aspx?id={R:1}" />
        </rule>
      </rules>
    </rewrite>

常見陷阱與解決方案

問題原因解決
CSS/JS/圖片 404頁面用相對路徑 css/site.css,重寫後路徑變 /CustomerList.aspx/css/site.css使用 根相對路徑 /css/site.css 或 Page.ResolveUrl("~/css/site.css")
PostBack 後網址變成重寫後路徑<form action 渲染為重寫後路徑在 Page_Load 設定 form1.Action = Request.RawUrl
驗證/授權失效<location path="Customers"> 對應原始路徑,但重寫後路徑不同授權規則寫重寫後路徑,或使用 HttpModule 在 AuthorizeRequest 事件自訂邏輯
無限重寫迴圈規則互相觸發加 stopProcessing="true"、檢查 Request.RawUrl 避免重複重寫

Pipeline vs Web Forms 概念釐清

ASP.NET Pipeline:每個請求必經的處理管線 (事件序列),屬於 ASP.NET 執行階層。
Web Forms:PageHandlerFactory 在 Pipeline 中選擇處理 .aspx 時,建構頁面生命週期 (Init、Load、Render) 的 頁面框架模型。
Pipeline 選擇 Handler → Handler 可能使用 Web Forms 模型 → 兩者層級不同,Pipeline 更基礎。

現代化建議

  • ASP.NET Framework 4.7+:使用 Microsoft.AspNetCore.Rewrite Middleware (需 OWIN 橋接) 或官方 URL Rewrite Module
  • ASP.NET Core:內建 app.UseRewriter() + RewriteOptions,支援 Regex、Apache mod_rewrite 規則轉換
  • 反向 Proxy 層:Nginx/IIS ARR/Apache mod_rewrite 在流量入口處理,應用程式完全感知不到重寫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved