5

使用 .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

4 回答 4

12

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

在视图中执行以下操作

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

然后在您的控制器中,只要您有错误,请执行以下操作

ModelState.AddModelError("BussinessError", your error)
于 2013-04-17T17:20:12.670 回答
4

我会看看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;
于 2013-04-17T17:35:47.280 回答
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);
          }
     }
}
于 2013-04-17T17:51:20.210 回答
0

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

您可以在此处找到有关如何更新 ModelState 的精彩讨论。

于 2013-04-17T17:20:38.677 回答