MVC 模型 > 视图模型设计模式

MVC Model > View Model Design Pattern

很抱歉,如果这个问题已经得到解答,但我正在寻找处理以下情况的最佳实践。

我有一个相当大的 MVC5 应用程序,其中有很多 forms/pages。

对于这个例子,假设我有一个像下面这样的病人 class(这是一个更大 class 的精简版)

    Public Class Patient {

    [Display(Name = "Patient Trial Number")]
    public int ID { get; set; }

    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Patient DOB")]
    public DateTime PatientDOB { get; set; }

    [Required]
    [Display(Name = "Patient Gender")]
    public Gender PatientGender { get; set; }

    } 

我需要填写的每种表格都有不同的模型。其中一些是非常大的 80+ 属性。

下面是表单模型的精简示例。

public class ExamplePatientForm

    {
        [Key]
        public Patient PatientID { get; set; }

        [Required]
        [Display(Name = "Was Sample One taken?")]
        public bool? SampleOneTaken{ get; set; }

        [Required]
        [Display(Name = "Date Sample One Taken")]
        public DateTime DateSampleOneTaken { get; set; }

        [Required]
        [Display(Name = "Was Sample Two taken?")]
        public bool? SampleTwoTaken{ get; set; }

        [Required]
        [Display(Name = "Date Sample Two Taken")]
        public DateTime DateSampleTwoTaken { get; set; }

        public int PatientRating {get;set;}

        public string Comments { get; set; }


    }

实际上,患者 class 和个体 class 都要大很多。

最初我使用 html.HiddenFor 将患者 class 的详细信息保存在各个表格中,尽管这感觉不对。

然后我创建了 ViewModel(见下文)

        [Key]
        public int PatientID { get; set; }

        [Required]
        [Display(Name = "Was Sample One taken?")]
        public bool? SampleOneTaken{ get; set; }

        [Required]
        [Display(Name = "Date Sample One Taken")]
        public DateTime DateSampleOneTaken { get; set; }

        [Required]
        [Display(Name = "Was Sample Two taken?")]
        public bool? SampleTwoTaken{ get; set; }

        [Required]
        [Display(Name = "Date Sample Two Taken")]
        public DateTime DateSampleTwoTaken { get; set; }

        public int PatientRating {get;set;}

        public string Comments { get; set; }


    }

ViewModel 删除了关系并将 PatientID 存储为整数。然后我将其映射回我的控制器中的实体模型。

尽管必须复制每个表单模型来创建视图模型对我来说似乎很疯狂,尤其是当一些包含 80 多个属性时。

有人知道解决这个问题的最佳方法吗?我将有大约 50 个独特的表格。

我还为患者模型创建了一个编辑器模板,这样我就可以在每个表单的顶部显示一些患者信息。但只需要显示某些属性,所以不确定我是否需要为此创建一个单独的 PatientViewModel 或只是隐藏其他元素。

希望这是有道理的。 任何帮助将不胜感激。

此致, 罗布

实际上,没有一个表单应该同时使用所有 80 个属性。如果是,那么我认为应该将表单分成多个屏幕。

话虽如此,ViewModel/InputModel 方法绝对是最佳实践。它允许您拥有所有 Patient 属性以及您需要的任何补充信息,例如下拉菜单的项目列表。您可以使用像 Automapper 这样的工具为您做映射,或者您可以手动完成,这完全取决于您,并且取决于 ViewModel 和域模型的匹配程度。我通常只是从 Entity Framework 直接对我的 ViewModel 执行 Select。

我强烈建议不要使用您的模型(实体)作为您的视图模型,因为这些是直接连接到您的 ORM 的模型,例如虽然 Entity Framework。这可能意味着,如果某人足够狡猾,他们可以更新他们可能不应该访问的属性(尽管 POST 或 GET 请求)。您的领域模型也应该非常薄,属性越少越好——没有 DisplayName(...) 之类的。

如果您的视图模型非常大,您应该将它们拆分并作为较小视图模型的属性重新使用。甚至可以创建一个工厂来建造它们。

如果需要一对一映射它们,AutoMapper 之类的工具会很方便,但我建议您手动映射或使用简单的自制映射器。

使用 viewmodel 显然是最好的方法,您必须在 viewmodel 中添加所有这 80 多个属性。您不应直接使用 domain model 中的属性。

此外,您的问题似乎是 UI design 而不是 programming desing,因此请尝试考虑按照其他人的建议更改您的 UI design。你肯定可以把表格分成不同的形式。

另请查看这两个链接,希望它们对您的疑虑有所帮助
Chris Pratt
Whosebug