基于bool方法的自定义MVC4验证

loy*_*low 3 c# asp.net validation asp.net-mvc-4

我有一个验证数字的方法,我没有这个的正则表达式,因为它有点复杂.

public bool IsRegistrationNumberValid(int number)
{
...

}
Run Code Online (Sandbox Code Playgroud)

在我的表单上,我有一个文本框,我想为此列添加验证.如何创建自定义注释或挂钩到ModelState对象以添加错误消息?

我的POST控制器动作如下:

    [HttpPost]
    public ActionResult Create(UserRegistrationViewData model)
    {
        if (ModelState.IsValid)
        {
        ...
        }
    }
Run Code Online (Sandbox Code Playgroud)

我不确定我有哪些选项,我可以创建一个自定义属性来添加到我的模型中吗?和/或者我应该挂钩到Model状态并在我检查之前添加错误消息ModelState.IsValid

Ben*_*ale 10

有几种方法,最适合您的方法取决于以下方面:

  • 您的IsRegistrationNumberValid方法位于何处以及逻辑是否被移动?
  • 您是在验证用户输入还是域的完整性(您应该检查两者,但每个的验证将在不同的位置)?
  • 个人喜好.

我看到它的方式你有以下选择:

  1. 在控制器操作方法中验证.
  2. 使用IValidatableObject界面验证.
  3. 使用自定义ValidationAttribute.
  4. 在服务层验证.

选项1:在您的控制器中验证:

首先,您可以简单地验证控制器操作方法中的值并更新ModelState如下:

[HttpPost]
public ActionResult Create(UserRegistrationViewData model)
{
    if (ModelState.IsValid)
    {
        if (!someObject.IsRegistrationNumberValid(model.value))
        {
            ModelState.AddModelError("PropertyName", "There is an error..");
            Return View()
        }
        else
        {
            // Carry out successful action here...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

选项2:使用IValidatableObject界面.

第二种更清洁的方法是IValidatableObject在viewModel上实现接口,以便您可以将逻辑移出控制器:

public class ViewModel : IValidatableObject
{
    public int Value { get; set; }

    IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
    {
        if (!staticClass.IsRegistrationNumberValid(this.Value))
        {
            yield return new ValidationResult("An error occured");
        }
}
Run Code Online (Sandbox Code Playgroud)

选项3:创建自定义验证属性.

如前所述,您可以通过从ValidationAttribute 本文中显示的派生来创建自定义验证属性.

IvalidatableObject接口和自定义验证属性之间的选择通常IValidatableObject取决于首选项,但是,接口获胜的一种情况是验证取决于多个属性(EG检查一个日期是否在另一个之后).

选项4:在服务层验证.

最后,如果您的验证依赖于数据库中的其他信息,您可能需要查看本教程中有关使用服务层进行验证的信息.这篇文章并不完美(服务和控制器有点紧密耦合)但是是一个良好的开端,只需进行一些修改,您就可以将数据库验证错误(例如主键违规)传递到用户界面中,并且用户非常透明-友好的方式.

您可能最终会使用选项2,3和4的混合.如果可能,您实际上并不想使用第一个选项,因为它会使控制器方法更复杂,并且使得在其他地方重用验证逻辑变得更加困难.

我的建议如下:

  • 如果要验证用户输入的完整性(EG检查日期格式是否正确),请使用IValidatableObject接口和ValidationAttribute类的混合.
  • 如果要验证域的完整性(确保未输入重复实体,或确定实体之间的关系),请在服务层中执行验证.