ASP.NET MVC3 Action Filter 控制輸出的 Layout

在開發 Mvc 的時候可能會用到 RenderAction 的方式去將其他 Action 輸出的結果一次回傳,RenderAction 回傳的結果會是比較簡單的,模組化之後的回傳。但是也有可能原本的 Action 已經是完整的頁面,但是可能為了需要過場特效或是各種原因她必須在某些狀況被包含在 Render 輸出。
原本預設的 Attribute 就有包含 [ChildActionOnly] 可以控制只能被包含在其他的回傳之中,配合 PartialView() 可以很容易做到單純子項目的輸出,但是今天想要的是可以把頁面回傳或是RenderAction 的回傳都一併處理掉。


public class ChildActionWithoutLayoutAttribute
: ActionFilterAttribute, IActionFilter, IResultFilter
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.IsChildAction)
{
try
{
((ViewResult)filterContext.Result).MasterName =
"~/Views/Shared/_Partial.cshtml";
}
catch
{
}
}
base.OnActionExecuted(filterContext);
}
}

利用 IsChildAction 的判斷可以在 OnActionExecuted 的時候去指定不同的 Master Page,要注意的是如果有在各個頁面中去各自指定的情況下,而不是統一由 _ViewStart.cshtml 統一指定的話,這個的 OnActionExecuted 必須改為 OnResultExecuted 才不會被頁面上的設置蓋掉。執行順序是 _ViewStart.cshtml > OnActionExecuted > View > OnResultExecuted

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

▲如果有在各自的 view 去額外設定的話,則要將 Action Filter 的事件延後
另外一個要注意的是,在這邊的 MasterName 設定為空字串或是 null 是沒有效果的,如果找不到值就會帶入預設的 Layout ,所以為了達到這個效果額外開了一個 _Partial.cshtml 裡面只有 @RenderBody() 一行。

如果要判斷是不是 Ajax 的請求也可以用  filterContext.HttpContext.Request.IsAjaxRequest() 來判斷。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *