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

ASP.NET MVC 3 實現 Server.Transfer 效果:動態切換 View 渲染路徑

     編輯:ASP.NET 基礎

問題背景

ASP.NET MVC 預設導向方式(`RedirectToAction`、`Redirect`、`RedirectToRoute`)皆為 HTTP 302 客戶端導向,基於 GET 請求,無法傳遞大型物件或複雜型別參數。WebForms 的 `Server.Transfer` 具備:

  1. 網址列不變
  2. 伺服器端直接轉移執行流程
  3. 上一頁面的物件/參數直接可用

MVC 中可透過動態指定 View 路徑達成類似效果。

實作三步驟

步驟 1:自訂 ViewEngine 限定搜尋路徑

public class DynamicViewEngine : RazorViewEngine
{
    public DynamicViewEngine(string controllerPath, string viewName)
    {
        // 僅搜尋指定路徑,跳過預設慣例
        ViewLocationFormats = new[]
        {
            $"~/Views/{controllerPath}/{viewName}.cshtml"
        };
        
        // 同樣處理 Partial View 與 Master/Layout
        PartialViewLocationFormats = ViewLocationFormats;
        MasterLocationFormats = ViewLocationFormats;
    }
}

步驟 2:建立 ActionFilterAttribute 動態註冊 ViewEngine

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class RenderViewAttribute : ActionFilterAttribute
{
    private readonly string _controllerPath;
    private readonly string _viewName;

    public RenderViewAttribute(string controllerPath, string viewName)
    {
        _controllerPath = controllerPath;
        _viewName = viewName;
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        // 將自訂 ViewEngine 加入搜尋鏈結最前端(優先權最高)
        ViewEngines.Engines.Insert(0, new DynamicViewEngine(_controllerPath, _viewName));
    }
}

步驟 3:在 Action 標註屬性指定目標 View

[HttpPost]
[RenderView("Invoice", "Create")] // 渲染 Views/Invoice/Create.cshtml
public ActionResult PreInvoice(string strIds, bool flag)
{
    // 業務邏輯處理...
    var model = PrepareInvoiceModel(strIds, flag);
    return View(model); // 實際渲染 Invoice/Create.cshtml
}

運作原理

  1. Action 執行完成,進入 Result 執行階段
  2. `OnResultExecuting` 將自訂 `DynamicViewEngine` 插入 `ViewEngines.Engines` 集合最前端
  3. `ViewResult` 執行時,`ViewEngineCollection` 依序詢問每個 Engine 尋找 View
  4. 自訂 Engine 回傳指定路徑的 View,搜尋結束
  5. 指定 View 使用當前 Action 的 Model 進行渲染

進階擴充:支援多種路徑模式

public class RenderViewAttribute : ActionFilterAttribute
{
    public string ViewPath { get; set; } // 完整相對路徑:~/Views/Invoice/Create.cshtml
    public string ControllerName { get; set; }
    public string ViewName { get; set; }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        string path;
        if (!string.IsNullOrEmpty(ViewPath))
            path = ViewPath;
        else if (!string.IsNullOrEmpty(ControllerName) && !string.IsNullOrEmpty(ViewName))
            path = $"~/Views/{ControllerName}/{ViewName}.cshtml";
        else
            return; // 使用預設慣例

        ViewEngines.Engines.Insert(0, new DynamicViewEngine(path));
    }
}

// 使用方式
[RenderView(ViewPath = "~/Views/Shared/Error.cshtml")]
[RenderView(ControllerName = "Report", ViewName = "Detail")]
public ActionResult SomeAction() { ... }

優缺點分析

優點缺點
保留 POST 資料與 ModelState 違反 PRG 模式,重新整理可能重複提交
可傳遞複雜物件參數 網址列不變,使用者無法書籤/分享特定狀態
單一請求完成,效能優於 Redirect 瀏覽器歷史紀錄不包含目標頁面
繞過授權過濾器(視實作而定) View 與 Controller 耦合度增加,測試較複雜

現代替代方案建議

  1. TempData:跨請求暫存複雜物件(Session 支援),配合 `RedirectToAction`
  2. Session/快取:大型物件暫存,Key 傳遞
  3. POST-Redirect-GET (PRG):標準模式,避免重複提交
  4. AJAX 表單提交:單頁應用體驗,回傳 Partial View 或 JSON
  5. ASP.NET Core:使用 `IActionResult` 回傳 `View("Path", model)` 直接指定路徑,無需自訂 ViewEngine

結語

動態切換 View 路徑是實現類 `Server.Transfer` 效果的巧妙手法,但僅建議在特定舊系統遷移或特殊業務場景使用。新專案應遵循 PRG 模式與 RESTful 設計,善用 TempData、AJAX 與客戶端狀態管理,構建可維護、可測試、符合 Web 標準的應用程式。

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