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

本文关键字:视图 模型 MVC 复杂 创建 ASP | 更新日期: 2023-09-27 18:02:19

创建和更新一个复杂的视图模型是我在做一个web项目时大部分时间都在挣扎的事情。

例如,我有一个PageViewModel,它需要一个背景图像URL和一个页面标题传递给_Layout.cshtml,所以

@model WebApplication.ViewModels.PageViewModel
<body background-image=@Model.BackgroundImageUrl>
   ...
</body

对于每个其他视图模型,我现在有2个选项:

  1. 源自PageViewModel
  2. PageViewModel上创建一个属性来保存特定的视图模型(组合优于继承等)

很明显,我更倾向于选项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操作出现任何问题,我需要重建整个视图模型图,这对于上面的示例来说不算太坏,但在现实世界的应用程序中,这将变得非常混乱(只需考虑使用来自存储的数据填充下拉列表)。控制器动作应该是精简的,不是吗?让视图模型负责检索它们自己的数据感觉也不对,所以我可能应该提出一个视图模型工厂。这反过来又会产生过多的工厂,每个视图模型一个工厂,这又会变得混乱。

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

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

可以考虑使用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>

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