ASP.NET MVC:使用基本强类型视图填充派生的强类型视图

时间:2009-09-23 02:08:57

标签: c# asp.net-mvc

在我的申请表中,我有不同的页面:联系我们,关于我们,主页

它们都具有相同的基本元素,需要填充视图:

  • 页面标题
  • 元描述
  • 用户信息

然而,在每个页面上,它们都有一些不同的元素:

联系我们

  • 联系信息模型
  • 联系表单模型

关于我们

  • 扩展用户信息模型

主页

  • 主页文字属性

它们都被路由到相同的Controller Action Method,因为除了根据页面类型填充“额外”信息之外,大多数功能都是类似的。

到目前为止,我已经做了以下事情:

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

然后我有:

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

问题是如何填充“额外”信息?我不确定我是否会以正确的方式做这件事。任何洞察力都可以更好地构建逻辑流程。

2 个答案:

答案 0 :(得分:3)

使用界面来暗示视图模型之间的某些共性肯定会有助于回答问题中的一些要点。

但是我会问,“重构”你的Action以支持不同数据结构的多个视图是多么明智。

MVC控制器操作通常表示收集生成预期视图所需的特定数据所需的最少代码量。单个操作返回相同模型数据的不同视图(例如Html视图或移动视图)并不是完全不常见,但通过改变数据结构和生成的视图会引入一些问题。

特别是你违反了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...
}

有几种方法可以重构视图模型代码的生成,但这是一种可能的模式。

我很欣赏这个答案确实有一定的意见,但我会考虑采取单独的行动作为最佳实践。

希望有所帮助。

答案 1 :(得分:1)

你问题的标题几乎可以给你答案。您可以使用某种形式的多态来完成此任务。您可以使用共享属性定义基类,或者使用以下类似的接口:

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

然后定义三个强类型的ViewModel类,它们都实现了这个接口(或从基类派生):

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

在每个ViewModel类上,添加这些视图所需的额外属性。

在您的Controller Action中,您需要打开PageType以选择正确的ViewModel并用数据填充它。

您还需要为每个ViewModel类创建三个强类型的不同视图(.aspx)。

如果您有公共数据的共享呈现,则可以将其提取到键入ICommonPage的强类型UserControl(.ascx)中。