在 MVC ASP.Net 视图模型中验证嵌套模型

本文关键字:模型 嵌套 验证 视图 MVC ASP Net | 更新日期: 2023-09-27 18:33:41

我有一个带有公司模型的应用程序。公司模型具有地址模型的导航属性(一对一关系(:

公司.cs

public class Company
{
    public int CompanyID { get; set; }
    public string Name { get; set; }
    // Snip...
    public virtual Address Address { get; set; }
}

我创建了一个视图模型来处理编辑、详图和创建操作:

公司视图模型.cs

public class CompanyViewModel
{
    public int CompanyID { get; set; }
    [Required]
    [StringLength(75, ErrorMessage = "Company Name cannot exceed 75 characters")]
    public string Name { get; set; }
    // Snip...
    public Address Address { get; set; }
}

我在控制器中使用AutoMapper在模型和视图模型之间来回映射,并且一切正常。但是,我现在想对地址对象使用验证 - 我不希望在没有地址的情况下创建公司。

我的第一个想法是简单的路线 - 我尝试在 Address 属性上放置"[必需]"注释。这什么也没做。

然后,我认为最好取消 Address 属性并在视图模型中抽象该数据,因此我将 Address 类中所有属性的属性添加到视图模型中:

public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
// etc....

这似乎是很好的做法,但现在我的自动映射器无法将这些属性映射到 Company 类的 Address 对象,所以我不得不在控制器中手动映射:

public ActionResult Details(int id = 0)
{
    // Snip code retrieving company from DB
    CompanyViewModel viewModel = new CompanyViewModel();
    viewModel.Name = company.Name;
    viewModel.Address1 = company.Address.Address1;
    // Snip...    
    return View(viewModel);
}

这导致我的控制器中有很多额外的代码,而不是一个漂亮的单行自动映射器语句......那么处理这个问题的正确方法是什么(验证视图模型中的嵌套模型(?

直接在视图模型中公开 Address 属性是一种好的做法,还是像我所做的那样使用单独的属性将其抽象出来更好?

自动映射器是否可以在源和目标不完全匹配的情况下工作?

在 MVC ASP.Net 视图模型中验证嵌套模型

如果您希望自动映射器能够在不显式指定映射的情况下将属性从模型映射到视图模型,则必须使用"扁平约定":表示您必须将导航属性的名称与其属性名称连接起来。

所以你的视图模型应该包含

public int CompanyID { get; set; }
    [Required]
    [StringLength(75, ErrorMessage = "Company Name cannot exceed 75 characters")]
    public string Name { get; set; }
    // Snip...
    //Address is the navigation property in Company, Address1 is the desired property from Address
    public string AddressAddress1 { get; set; }
    public string AddressAddress2 { get; set; }
    public string AddressCity { get; set; }
    public string AddressPostalCode { get; set; }
}

顺便说一下,您还可以告诉AutoMapper映射不明确遵循命名约定的属性:

Mapper.CreateMap<Company, CompanyViewModel>()
.ForMember(dest => dest.Address1, opt => opt.MapFrom(src => src.Address.Address1));
相关文章: