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