3

我有一个验证数字的方法,我没有正则表达式,因为创建起来有点复杂。

public bool IsRegistrationNumberValid(int number)
{
...

}

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

我的 POST 控制器操作如下:

    [HttpPost]
    public ActionResult Create(UserRegistrationViewData model)
    {
        if (ModelState.IsValid)
        {
        ...
        }
    }

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

4

1 回答 1

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...
        }
    }
}

选项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");
        }
}

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

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

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

选项 4:在您的服务层中验证。

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

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

我的建议如下:

  • 如果您正在验证用户输入的完整性(例如检查日期格式是否正确),请混合使用IValidatableObject接口和ValidationAttribute类。
  • 如果您正在验证域的完整性(确保没有输入重复的实体,或者定义了实体之间的关系),请在服务层中执行验证。 
于 2013-04-16T18:33:17.240 回答