如何在ASP.NET MVC中创建复杂的视图模型?

时间:2016-08-13 07:19:28

标签: c# asp.net-mvc asp.net-mvc-viewmodel

创建和更新复杂的视图模型是我在处理Web项目时大部分时间都在努力的方法。

例如,我有一个PageViewModel,它会将背景图片网址和网页标题传递给_Layout.cshtml,所以

@model WebApplication.ViewModels.PageViewModel

<body background-image=@Model.BackgroundImageUrl>
   ...
</body

至于其他所有视图模型,我现在有两个选项:

  1. PageViewModel
  2. 派生
  3. PageViewModel上创建一个属性来保存特定的视图模型(合成而不是继承等)。
  4. 由于显而易见的原因,我更倾向于选项2.无论如何,对于GET操作,我现在需要初始化PageViewModel中的所有属性以及视图模型中的属性实际上需要一个特定的行动,例如

    public PageViewModel
    {
        public string BackgroundImageUrl { get; set; }
        public ContactViewModel Contact { get; set; }
    }
    

    创建类似

    public IActionResult Contact(int contactId)
    {
       ...
       var viewmodel = new PageViewModel
       {
          BackgroundImageUrl = ...,
          ContactViewModel = new 
          {
             ...
          }
       }
    }
    
    对我而言,这是灾难的秘诀。

    POST上的事情变得更糟,因为理想情况下我只会发布与相关行动相关的字段,即

    public IActionResult Contact(ContactViewModel viewmodel)
    {
       if (ModelState.IsValid)
       {
          ... (this is the easy case)
          return RedirectToAction(...)
       }
    
       ... (now we have a problem)
    }
    

    如果在POST动作中出现任何问题,我需要重建整个视图模型图,这对于上面的示例来说并不是太糟糕,但在现实世界的应用程序中,这会非常快速地混乱(只是想到使用来自商店的数据填充下拉列表)。控制器动作应该是精益的,不是吗?让视图模型负责检索自己的数据也是不对的,所以我应该想出一个视图模型工厂。反过来,这会产生大量的工厂,每个工厂都会看到一个工厂,这个工厂也会变得混乱。

    我想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:2)

考虑的一种可能性是使用负责布局某些部分的child action

例如,您可以使用以下子操作来负责填充背景图像URL:

[ChildActionOnly]
public ActionResult BackgroundImage() 
{
    var model = new MyViewModel
    {
        BackgroundImageUrl = ...
    };
    return PartialView(model);
}

然后有一个相应的局部视图:

@model MyViewModel

<img src="@Model.BackgroundImageUrl" alt="" />

可以包含在您的主布局中(在这种情况下,它不需要视图模型,因为它的不同部分将从子动作组合):

<body>
    @Html.Action("BackgroundImage", "SomeController")
    ...
</body>

使用此方法,负责渲染视图的主要操作不需要知道和组装复杂的视图模型。它将只关注其特定的视图模型。

相关问题