在控制器中使用视图模型时,如何在实体内部保留验证规则?

Joh*_*ean 6 c# validation asp.net-mvc entity-framework asp.net-mvc-5

所以我的Models目录中有一个实体:

public class Event
{
    public int Id { get; set; }

    [Required, MaxLength(50), MinLength(3)]
    public string Name { get; set; }

    [Required, MaxLength(2000)]
    public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想使用viewModel将它公开给视图:

public class BaseEventViewModel
{
    public string Name { get; set; }

    [DataType(DataType.MultilineText)]
    public string Description { get; set; }
}

public class EventCreateViewModel : BaseEventViewModel
{

}
Run Code Online (Sandbox Code Playgroud)

我的理由是,我希望在实体上完成所有数据验证,并在视图模型上完成所有演示内容(例如渲染文本区域).然后,我可以使用许多我希望代表我的实体的视图模型,同时保持数据完整性.

所以我改变了控制器以使用新的视图模型:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(EventCreateViewModel viewModel)
    {
        if (ModelState.IsValid)
        {
            db.Events.Add(new Event
            {
                Name = viewModel.Name,
                Description = viewModel.Description
            });
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(viewModel);
    }
Run Code Online (Sandbox Code Playgroud)

但是,没有一个实体验证完成,我能够提交一个引发DbEntityValidationException异常的空白表单.

大概这是因为ModelState.IsValid正在处理视图模型,而不是视图模型所代表的实体.如何捕获这些验证错误?

Joh*_*ean 5

在向正确的方向刺激后,我实际上找到了答案.如果我将此注释添加到我的视图模型中,它将继承应用于我的实体上的属性的所有注释:

[MetadataType(typeof(Event))]
public class BaseEventViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    [DataType(DataType.MultilineText)]
    public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,当我提交一张空白表格时,我会正常显示验证错误.

这确实伴随着必须在我的视图模型中再次重新定义每个属性的警告,这类视图模型只能保留您需要的属性,但它适用于我的情况.


小智 0

在这种情况下,您的验证规则应该位于视图模型上。您正在做的工作是验证用户输入,这就是您用来接收输入的工作。

您可以在将实体写入数据库之前对实体执行单独的验证步骤。在这种情况下,您将使用单独的验证机制来处理实体上的规则。

  • @KingIsaac - 视图不应该信任用户,控制器不应该信任视图,数据库不应该信任调用者。对每个步骤(甚至数据库)进行验证是个好主意,不应跳过。 (2认同)
  • @KingIsaac:验证应该在所有层上完成,数据层可以由其他程序集使用,例如批量导入或非Web前端。 (2认同)