我一直在試圖找到一種很好的方式來處理我們的Asp.net MVC網站的模型,當有所有頁面的共同屬性。這些屬性將顯示在佈局(主頁面)中。我使用一個「BaseModel」類來保存這些屬性,我的Layout使用這個BaseModel作爲它的模型。Asp.net MVC模型的視圖和佈局
每個其他模型都從該BaseModel繼承,並且每個模型都具有相對於它所表示的視圖的特定屬性。正如你可能已經猜到的那樣,我的模型實際上是視圖模型,即使這在這裏不太相關。
我曾嘗試不同的方法來初始化BaseModel在每個視圖
- 通過「手」(這樣特定的控制器可以實現特定的對於爲例共同的行爲)
- 具有基礎controlelr是覆蓋OnActionExecuting調用初始化方法
- 使用一個輔助類做控制器之外
- 使用模型廠
但無那些真正吸引我:
- 似乎是顯而易見的我,但乾的理由一個足夠的理由認爲(其實我從來沒有嘗試過的解決方案可言,我只是把它放在最後一點能夠循環)。
- 我不喜歡那個,因爲這意味着無論何時添加一個新的Controller,都需要知道它必須從BaseController繼承,並且需要調用Initialize方法,更不用說如果您的控制器已經覆蓋了基本的一個,無論如何調用基地來維護這些值。
- 請參閱下一點
- 和3.是同一主題的變體,但對第二個解決方案的問題沒有幫助。
- 到目前爲止我的最愛,但現在我必須通過幾個變量來設置這些值。我喜歡它的依賴性倒置。但是,如果我想提供會話中的值,我需要將它們明確地傳遞給例子,然後我回到原點,因爲我必須手動提供它們(作爲參考或通過任何類型的接口)
當然,(幾乎)所有這些解決方案都有效,但我正在尋找一種更好的方法來實現。
在輸入這個問題時,我發現可能有一個新的路徑builder pattern,但實現也可能很快成爲一個負擔,因爲我們可以有幾十個視圖和控制器。
我會很樂意接受任何嚴肅的建議/提示/建議/模式/建議!
更新
感謝@EBarr我想出了另一種解決方案,使用ActionFilterAttribute(不生產代碼,這樣做是在5分鐘內):
public class ModelAttribute : ActionFilterAttribute
{
public Type ModelType { get; private set; }
public ModelAttribute(string typeName) : this(Type.GetType(typeName)) { }
public ModelAttribute(Type modelType)
{
if(modelType == null) { throw new ArgumentNullException("modelType"); }
ModelType = modelType;
if (!typeof(BaseModel).IsAssignableFrom(ModelType))
{
throw new ArgumentException("model type should inherit BaseModel");
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var model = ModelFactory.GetModel(ModelType);
var foo = filterContext.RequestContext.HttpContext.Session["foo"] as Foo;
model.Foo = foo;
model.Bar = somevalue;
filterContext.Controller.TempData["model"] = model;
}
}
稱它是那麼很簡單:
[Model(typeof(HomeModel))]
public ActionResult Index()
{
var homeModel = TempData["model"] as HomeModel;
// Add View Specific stuff
return View(homeModel);
}
它給了我最好的每一個世界。唯一的缺點是要找到一種合適的方式將模型傳遞迴動作。
這裏使用TempData對象完成,但我也考慮更新可以在ActionParameters中找到的模型。
我仍然採取任何嚴重的建議/提示/建議/模式/建議,或以前的觀點。
感謝您的反饋。雖然它不完全符合我的要求(您的解決方案是3的不同實現),但它實際上給了我一個想法。我只是嘗試使用一個自定義的ActionFilterAttribute,似乎可以做到這一點。我仍然需要設計一種「乾淨」的方式來讓模型回到動作中(現在我正在使用TempData)。我會更新這個問題來反映這一點。 – 2012-04-03 14:02:03
是的,它是#3的一個版本。我想過屬性,但是需要裝飾每個控制器/動作(取決於需要)。在OnActionExecuting和OnActionExecuted中保存我的代碼保存在一個基本控制器中。在實踐中,對於任何更大的MVC項目,您將擁有一個基本控制器,所以我不介意這麼多。它還允許我基於模型類型運行邏輯,而不是綁定執行操作的邏輯。 – EBarr 2012-04-03 14:07:35
RE:抓取模型:在你的動作過濾器屬性中,你將最終實現相同的事件(執行和執行),但是你可以從filterContext中取出模型,不需要把它交回,只需找到它並填寫你需要的東西。 – EBarr 2012-04-03 14:29:23