ASP.NET MVC 預設導向方式(`RedirectToAction`、`Redirect`、`RedirectToRoute`)皆為 HTTP 302 客戶端導向,基於 GET 請求,無法傳遞大型物件或複雜型別參數。WebForms 的 `Server.Transfer` 具備:
MVC 中可透過動態指定 View 路徑達成類似效果。
public class DynamicViewEngine : RazorViewEngine
{
public DynamicViewEngine(string controllerPath, string viewName)
{
// 僅搜尋指定路徑,跳過預設慣例
ViewLocationFormats = new[]
{
$"~/Views/{controllerPath}/{viewName}.cshtml"
};
// 同樣處理 Partial View 與 Master/Layout
PartialViewLocationFormats = ViewLocationFormats;
MasterLocationFormats = ViewLocationFormats;
}
}
[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));
}
}
[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
}
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 耦合度增加,測試較複雜 |
動態切換 View 路徑是實現類 `Server.Transfer` 效果的巧妙手法,但僅建議在特定舊系統遷移或特殊業務場景使用。新專案應遵循 PRG 模式與 RESTful 設計,善用 TempData、AJAX 與客戶端狀態管理,構建可維護、可測試、符合 Web 標準的應用程式。