.NET MVC自定义验证(无数据注释)

时间:2013-04-17 17:13:41

标签: asp.net-mvc validation

使用.NET MVC和代码优先EF来实现所请求的功能。业务对象相对复杂,我使用System.ComponentModel.DataAnnotations.IValidatableObject来验证业务对象 现在我试图找到方法,如何使用MVC ValidationSummary显示业务对象的验证结果,而不使用数据注释。例如(非常简化):

业务对象:

    public class MyBusinessObject : BaseEntity, IValidatableObject
    {
        public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
           return Validate();
        }
        public IEnumerable<ValidationResult> Validate()
        {
           List<ValidationResult> results = new List<ValidationResult>();

           if (DealType == DealTypes.NotSet)
           {
                results.Add(new ValidationResult("BO.DealType.NotSet", new[] { "DealType" }));
           }

           return results.Count > 0 ? results.AsEnumerable() : null;
        }
    }

现在我的MVC控制器中有这样的东西:

    public class MyController : Controller
    {
        [HttpPost]
        public ActionResult New(MyModel myModel)
        {
           MyBusinessObject bo = GetBoFromModel(myModel);
           IEnumerable<ValidationResult> result = bo.Validate();
           if(result == null)
           {
               //Save bo, using my services layer
               //return RedirectResult to success page
           }

           return View(myModel);
        }
    }

在视图中,我有Html.ValidationSummary(); 如何将IEnumerable<ValidationResult>传递给ValidationSummary?

我试图通过谷歌搜索找到答案,但我发现的所有示例都描述了如何使用模型中的数据注释而不是商业对象中显示验证摘要。

由于

4 个答案:

答案 0 :(得分:12)

在模型中添加属性,比如BusinessError,

在视图中执行以下操作

  @Html.ValidationMessageFor(model => model.BusinessError)

然后在您的控制器出现错误时执行以下操作

ModelState.AddModelError("BussinessError", your error)

答案 1 :(得分:2)

我会看看FluentValidation。它是一个没有数据通知的验证框架。我在一些复杂验证项目中使用它非常成功,并且它也可以在MVC项目之外使用。

以下是其页面中的示例代码:

using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Company).NotNull();
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

答案 2 :(得分:1)

如果存在验证错误,

实体框架应抛出DbEntityValidationException。然后,您可以使用该例外将错误添加到ModelState

try
{
     SaveChanges();
}
catch (DbEntityValidationException ex)
{
     AddDbErrorsToModelState(ex);
}
return View(myModel);

protected void AddDbErrorsToModelState(DbEntityValidationException ex)
{
     foreach (var validationErrors in ex.EntityValidationErrors)
     {
          foreach (var validationError in validationErrors.ValidationErrors)
          {
               ModelState.AddModelError(validationError.PropertyName, validationError.ErrorMessage);
          }
     }
}

答案 3 :(得分:0)

传递IEnumerate内容并继续利用Html.ValidationSummary的方法之一是更新ModelState。

您可以找到有关如何更新ModelState here的详细讨论。