2012-03-16 75 views
4

我正在研究一個MVC3 Razor Web應用程序,它從Java內容管理系統獲取它的頁面裝飾。由於這裝潢是由每個頁面共享,我已經把在_Layout.cshtml文件中的CMS內容的檢索,但我不是,我實現的代碼完全滿意...Razor中的嵌入式代碼_Layout.cshtml

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    @{ 
     -- The first two lines are temporary and will be removed soon. 
     var identity = new GenericIdentity("", "", true); 
     var principal = new GenericPrincipal(identity, new string[] { }); 
     var cmsInterface = MvcApplication.WindsorContainer.Resolve<ICMSInterface>(); 
     cmsInterface.LoadContent(principal, 2); 
    } 
    @Html.Raw(cmsInterface.GetHeadSection()) 
</head> 

<body> 
    @Html.Raw(cmsInterface.GetBodySection(0)) 
    @RenderBody() 
    @Html.Raw(cmsInterface.GetBodySection(1)) 
</body> 
</html> 

由於有是_layout文件沒有控制器我看不到我可以把代碼做檢索。以下是我考慮的幾件事情:

  • 檢索CMS內容的單獨部分,因此我不需要LoadContent調用。不幸的是,由於我必須使用組件來檢索CMS內容,所以這是不可能的,它是全部或全部。
  • 使用局部視圖,以便我可以使用控制器。因爲我需要將整個頁面放入部分選項中,這看起來有點荒謬。
  • 在檢索數據並將三個部分添加到ViewBag的某個輔助類中調用單個靜態方法。這將允許我將代碼移出視圖,並感覺像是最好的解決方案,但我仍然不是特別滿意。

有沒有人有任何其他的建議/意見?

回答

5

您可以使用全球行動濾波器所需的數據添加到ViewBag在所有控制器:

public class LoadCmsAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     if (!filterContext.IsChildAction && 
      !filterContext.HttpContext.Request.IsAjaxRequest() && 
      filterContext.Result is ViewResult) 
     { 
      var identity = new GenericIdentity("", "", true); 
      var principal = new GenericPrincipal(identity, new string[] { }); 
      var cmsInterface = MvcApp.WindsorContainer.Resolve<ICMSInterface>(); 
      cmsInterface.LoadContent(principal, 2); 

      var viewBag = filterContext.Controller.ViewBag; 
      viewBag.HeadSection = cmsInterface.GetHeadSection(); 
      viewBag.FirstBodySection = cmsInterface.BodySection(0); 
      viewBag.SecondBodySection = cmsInterface.BodySection(1); 
     } 
    } 
} 

的Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    ... 
    filters.Add(new LoadCmsAttribute()); 
} 
+0

這看起來像一個很好的解決方案,但我是否認爲這會發生在每一個行動?我不希望代碼執行任何部分視圖或json操作。 – DoctorMick 2012-03-27 14:09:26

+0

我更新了代碼,因此它只能在正常操作中執行。 – 2012-03-27 15:02:53

1

一種解決方案:

  1. 創建基礎控制器,每個控制器,從繼承。
  2. 覆蓋OnActionExecuted或類似的概述
  3. 添加數據到ViewBog或ViewData的在你重寫代碼

的OnActionExecuted代碼會被執行每一個動作被調用的時候,所以你可能要進行一些檢查以確保該動作將返回一個視圖,等等。可能有更好的重寫OnActionExecuting,OnResultExecuting等等,但這是我頭腦中最重要的一個。

另一種解決方案:

創建你可以用它來裝點你的控制器的過濾器屬性。

http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

這可能是一個更好的解決辦法,如果你不希望有一個基本的控制器。

1

*「由於_layout文件沒有控制器」。* 問題是,您的假設不完全正確!事實上,在控制器的幫助下填充_Layout頁面是很常見的。讓我們想想例如很多網站的登錄/註銷矩形......它通常放在_Layout中並通過控制器進行處理。 沒有控制器將ViewModel傳遞給佈局...僅僅是因爲佈局...只是...佈局而不是傳達信息的東西...它可以成爲其他內容的「容器」反過來可能有一個ViewModel。 實際上,您可以使用Html.Action或Html.RenderAction從_Layout調用Child控制器...這是登錄在大多數asp.net Mvc網站中處理的方式......我建議您執行同樣適用於您的內容...通過調用專門的子控制器來填充您的內容,其中一個用於佈局頁面的每個不同「區域」。

+0

我這樣做可以看到的唯一問題是我需要將數據傳遞給所有不同的控制器操作,因爲我只想調用一次LoadContent方法。我是否誤解了您建議的解決方案中的某些內容?是否可以在不同的控制器動作之間傳遞狀態數據(不使用viewbag)? – DoctorMick 2012-03-27 14:08:07

+0

可能你誤解了我的建議。 Probaby你只需要1-2個控制器。 1-2之間的選擇......僅取決於模塊性問題......這取決於您的選擇。只需在你的_layout中放入一個Html.Action或一個只調用一個控制器的Html.RenderAction。這樣,您將始終使用相同的控制器填充您的_layout的一部分...這意味着相同的控制器會爲使用該_layout頁面的所有視圖執行相應的工作。 如果您希望有多個控制器分別填充_layout的不同部分,您可以選擇使用多個Html.Action。這取決於您。 – 2012-03-27 14:16:57