MVC 和嵌套视图模型的困难

Difficulties with MVC and nested Viewmodels

我对 MVC 还很陌生,所以请记住这一点

我创建了一个视图模型 vmRecurringPack,其中包含另一个模型 Entity 以及其属性中的其他字段。在我传递 vmRecurringPack 的视图中,我仅使用一些 Entity 属性用于显示目的(我的视图不需要其余字段)

我的问题在于,当我 POST 我的视图返回时,其余字段当然没有绑定到视图,并且失去了它们的价值。这部分对我来说很好,但是 ModelState.IsValid 不再有效,因为其中一些字段是必需的。

如何在不删除 ModelState.IsValid 的情况下解决这个问题?

(VB.net 最好回答,欢迎 C#)

编辑:我考虑过重构我的视图模型,这会起作用,但是我很好奇存在哪些其他解决方案

编辑:按要求编写代码。尽管我看不出这个特定问题的要求...关于我的问题,我想显示 vmRecurringPack.Entity.CodevmRecurringPack.Entity.Name 的字段,但在我的表单中 POST ModelState.IsValid returns 错误,因为 Entity 中标记为必填的字段毫无意义

vmRecurringPack

Namespace ViewModels
Public Class vmRecurringPack

    Property Entity As Entity
    Property Name As String
    Property Description As String
    Property Status As String

End Class
End Namespace

实体

Namespace Models
Public Class Entity
    Public Property Id As Integer

    <Required>
    Public Property Name As String

    <Required>
    <StringLength(5)>
    Public Property Code As String

    <Required>
    <StringLength(7)>
    Public Property Abbrv As String
    Public Property Status As Boolean

    <DataType(DataType.EmailAddress)>
    Public Property Email As String

    Public Overridable Property EntityType As EntityType
    Public Overridable Property ReportLists As ICollection(Of ReportList) = New HashSet(Of ReportList)
    Public Overridable Property Packages As ICollection(Of Packages) = New HashSet(Of Packages)

End Class
End Namespace

视图模型是一种对发送到视图的数据进行建模的方法,因此如果从浏览器发送到服务器的数据不同,则常见的方法是创建新的输入模型类型。

public ActionResult Edit()
{
    return View(new RecurringPackViewModel(...));
}

[HttpPost]
public ActionResult Create(RecurringPackInputModel model)
{
    if (ModelState.IsValid)
    { 
       ... 
    }
}

这样您的视图模型和输入模型都可以有不同的要求。

重构视图模型是处理此问题的正确方法。如果它们完全适合您的场景,重用视图模型是一件好事,但您不应该修改验证 logic/change 应用程序逻辑,以便您可以重用相同的视图。如果您将几个 Entity 属性用于显示目的,而不是仅将这些属性添加到您的 vmRecurringPack 对象而不对其应用任何验证规则。

在您的情况下,如果您坚持使用原始视图模型,则可能必须实施自定义验证逻辑。例如 FluentValidation 等库允许您定义复杂的验证规则。

使用视图模型的指南正是为了避免您遇到的此类问题。您在此处使用了视图模型,但您只是将实体 class 作为 属性 附加到它上面。如果您不需要实体上的所有内容,那么也可以为它创建一个视图模型。一般来说,将任何实体 class 发送到您的视图都是一个坏主意(即使它是通过另一个 class 上的 属性)。 100 次中有 99 次,你会发现自己又回到了这里,无论如何都需要用视图模型将其切换出去。