2009-09-23 130 views
1

在我的應用程序有不同的網頁:聯繫我們,關於我們,首頁ASP.NET MVC:填充派生的強類型視圖與基強類型查看

他們都需要填充的觀點相同的基本要素:

  • 頁面標題
  • meta描述
  • 用戶信息

但是在每一頁上,他們有一些元素是不同的:

聯繫我們

  • 聯繫信息模型
  • 聯繫表型號

關於我們

  • 擴展用戶信息模型

首頁

  • 首頁文本屬性

他們都路由到同一個控制器的操作方法,因爲大多數的功能比填充「額外」的信息類似的其他依賴頁面類型。

到目前爲止,我已經做了一些,其中:

PageDetailViewData pageDetailViewData = new PageDetailViewData {Title = title, Desc = desc....} 

並且在這之後,我有:

   switch ((PageType)page.PageType) 
      { 
       case (PageType.Contact): 
        return View("ContactUsDetails", pageDetailViewData); 
       default: 
        return View(pageDetailViewData); 
      } 

的問題是,我該如何填寫「額外」的信息?我不確定我是否正在以正確的方式做這件事。任何洞察,以更好地構建邏輯流程將不勝感激。

回答

3

使用接口暗示您的視圖模型之間有一些共同點的答案肯定會有助於回答您的問題中的一些觀點。

然而,我會問,「重構」你的行動是多麼明智,以支持不同數據結構的多個視圖。

MVC控制器操作通常代表收集生成預期視圖所需的特定數據所需的最少代碼量。單個動作返回同一模型數據的不同視圖(例如Html視圖或Mobile視圖)並不罕見,但通過改變數據結構和視圖會產生一些問題。

特別是,您違反了常見的最佳實踐,如Single Responsibility Principle,並使您的代碼更加複雜以進行測試 - 無痛測試和TDD是ASP.Net MVC的重大勝利的一部分。

就我個人而言,我會有一個單獨的行動。

就你的視圖模型而言,如果這是一個數據庫,你會怎麼做? 你會分開查詢單獨的數據權利?

用戶的個人資料信息將與頁面元數據信息分開查詢。這可能是由於許多原因造成的,這些原因可能包括高速緩存數據的某些部分而不是其他數據。

因此,與上述建議,你的代碼可能是這樣的(注意:此代碼不能在Visual Studio編寫,是完全可能的語法問題):

public interface IMetaDataViewModel 
{ 
    PageMetaData MetaData{get; set;} 
} 
public class HomeViewModel : IMetaDataViewModel 
{ 
    public PageMetaData MetaData{get; set;} 
    public string HomePageText{get; set;} 
} 
//other view models go here.... 

public class CommonPagesController : Controller 
{ 
    private MetaDataProvider _metaProvider = new MetaDataProvider(); 
    private PageDataProvider _pageDataProvider = new PageDataProvider(); 
    private ContactDataProvider _contactDataProvider = new ContactDataProvider(); 

    public ActionResult Home() 
    { 
     var viewModel = new HomeViewModel 
     { 
      MetaData = _metaProvider.GetPageMeta(); 
      HomePageText = _pageDataProvider.GetPageData(); 
     }; 
     return View(viewModel); 
    } 
    public ActionResult Contact() 
    { 
     var viewModel = new ContactViewModel 
     { 
      MetaData = _metaProvider.GetPageMeta(); 
      ContactFormData = _contactDataProvider.GetData(); 
     }; 
     return View(viewModel); 
    } 
    //you get the picture... 
} 

有幾種方法,你也可以重構視圖模型代碼的生成,但這是一種可能的模式。

我明白,這個答案確實有一定的意見,但我會考慮分開行動是最好的做法。

希望有所幫助。

+0

感謝您的詳細回覆。所有路由到同一個Action Handler的原因是因爲傳入的「Action」是動態的,並且只有在查詢數據庫時才確定頁面類型。例如:site.com/ABC site.com/contact-ABC ...我只知道依賴於域之後的密鑰取決於哪個視圖。 – TimLeung 2009-09-24 03:24:18

+0

也許您需要的抽象不在控制器級別,但可能在Controller Factory級別? 如果你想堅持強類型的視圖路線(通常是一件好事),那麼你將不得不編寫自定義代碼來填充每個視圖模型。 聽起來你正在編寫一個CMS風格的應用程序。這可能是我一次積極辯論強類型觀點的優點的時候。我還沒有看到......但值得考慮。 – 2009-09-24 08:37:28

1

問題的標題幾乎給你答案。你可以使用某種形式的多態來實現這一點。可以定義一個基類與所述共享屬性,或者可替換地是這樣的接口:

public interface ICommonPage 
{ 
    string Title { get; } 
    string MetaDescription { get; } 
    string UserInformation { get; } 
} 

然後定義三個強類型視圖模型類,所有實現這個接口(或從基類派生):

  • ContactUsViewModel:ICommonPage
  • AboutUsViewModel:ICommonPage
  • HomeViewModel:ICommonPage

在這些ViewModel類的每一個上,都添加了這些視圖所需的額外屬性。

在您的Controller Action中,您需要打開PageType以選擇正確的ViewModel並使用數據填充它。

您還需要爲每個ViewModel類創建三個不同的視圖(.aspx)。

如果您已經共享通用數據的渲染,那麼可以將其提取到鍵入ICommonPage的強類型UserControl(.ascx)中。

+0

實例化派生視圖模型的最佳方法是什麼?填充基本信息的最佳方式是什麼?我應該將人口抽象爲一種方法嗎? – TimLeung 2009-09-23 13:03:05

+0

一般來說,如果您可以保持ViewModel被動,並使其成爲Controller(或另一個類)填充數據的責任,那麼最好。這也是您需要選擇正確的ViewModel類型的地方。 – 2009-09-23 13:30:37