验证包含嵌套域对象的Viewmodel

时间:2012-04-11 15:29:30

标签: asp.net-mvc

我有以下两个实体:

 public class Product
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual Category Category { get; set; }
}
public class Category
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}

和视图模型

public class ProductCreateOrEditViewModel
{
    public Product Product { get; set; }
    public IEnumerable<Category> Categories { get; set; }
}

Product的create视图使用此ViewModel。类别ID在视图中设置如下:

<div class="editor-field">
@Html.DropDownListFor(model => model.Product.Category.ID,new SelectList   
(Model.Categories,"ID","Name"))
    @Html.ValidationMessageFor(model => model.Product.Category.ID)
</div>

当表单发布时,我获得了一个带有产品和所选类别对象集的视图模型的实例,但由于Category的“Name”属性具有[Required]属性,因此ModelState无效。

就创建产品而言,我不需要或不关心“名称”属性。如何使模型绑定工作,以便不将其报告为ModelState错误?

1 个答案:

答案 0 :(得分:4)

您应该为View创建一个正确的ViewModel。

最好的方法imo不会将您的域实体暴露给视图。

您应该从实体到视图模型进行简单的DTO展平。

这样的课程

public class ProductViewModel
{
   public int ID { get; set; }
   [Required]
   public string Name { get; set; }
   public int CategoryId? { get; set; }
   public SelectList Categories { get; set; }
}

从控制器中将产品映射到viewmodel

public ViewResult MyAction(int id)
{
   Product model = repository.Get(id);

   //check if not null etc. etc.

   var viewModel = new ProductViewModel();
   viewModel.Name = model.Name;
   viewModel.CategoryId = model.Category.Id;
   viewModel.Categories = new SelectList(categoriesRepo.GetAll(), "Id", "Name", viewModel.CategoryId)

   return View(viewModel);
}

然后,在回复帖子的操作中,您将viewModel映射回产品

[HttpPost]
public ViewResult MyAction(ProductViewModel viewModel)
{
   //do the inverse mapping and save the product
}

我希望你明白这个想法