在asp.net MVC 5控制器中将验证逻辑与业务逻辑分开

时间:2016-10-19 15:12:20

标签: asp.net-mvc asp.net-mvc-5

我有一个asp.net MVC 5网站。

我在模型上使用数据注释进行验证 - 例如

[Required]
public string FirstName { get; set; }

但是,如果我想做一些更复杂的验证,比如说要求将来一个日期 - 我看到的所有例子都只是在控制器中执行验证 - 例如:

[HttpPost]
public ActionResult Edit(MyViewModel vm)
{
    // check date is in future
    if (vm.mydate < DateTime.Now())
        ModelState.IsValid = false;

    if (ModelState.IsValid)
    {
        //Business Logic
    }

即使是Web窗体,您也可以将验证逻辑分离为CustomValidator。将验证逻辑直接放入控制器并将其与业务逻辑混合在一起感觉是错误的。

(注意 - 虽然我想回答如何使用数据注释解决这些特定问题 - 我还想回答关于将验证逻辑分离出来的更大问题。)

是否有最佳实践或框架强制要求将其分开?我在网上找到的任何示例网站中都没有看到它。

我是否过度担心这一点 - 这是控制器执行验证的目的的一部分吗?我的业务逻辑应该在模型中吗? (BL在很大程度上只是写入数据库,所以也许它甚至不算BL?)。

THX。

1 个答案:

答案 0 :(得分:2)

You need to implement your custom Validation Attribute.

Create a new class and add:

public sealed class ValidFutureDate : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            DateTime InputDate = Convert.ToDateTime(value);

            if (InputDate <= DateTime.Now)
            {
                return new ValidationResult("Inputed date must be in the future.");
            }
        }
        return ValidationResult.Success;
    }
}

You need to add a reference to System.ComponentModel.DataAnnotations

And in your ViewModel, you can use the attribute like all the rest:

[Required]
[ValidFutureDate]
public DateTime Date { get; set; }