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

时间:2021-12-14 16:39:24

use .NET MVC and code-first EF to implement of requested functionality. Business objects are relatively complex and I use System.ComponentModel.DataAnnotations.IValidatableObject to validate business object.
Now I'm trying to find the way, how to show validation result from business object, using MVC ValidationSummary without using data annotations. For example (very simplified):

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

Business Object:

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

Now in my MVC controller I have something like this:

现在在我的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);
        }
    }

In view, I have Html.ValidationSummary();.
How I can pass IEnumerable<ValidationResult> to the ValidationSummary?

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

I tried to find an answer by googling, but all examples I found describes how to show validation summary using data annotations in Model and not in Business object.

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

Thanks

4 个解决方案

#1


11  

Add property, say BusinessError, in the model

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

in the View do the following

在视图中执行以下操作

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

Then in your controller whenever you have error do the following

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

ModelState.AddModelError("BussinessError", your error)

#2


2  

I would have a look at FluentValidation. It's a framework for validation without data annoations. I've used it with great success in some projects for complex validation, and it is also usable outside of the MVC-project.

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

Here is the sample code from their page:

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

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;

#3


1  

Entity Framework should throw a DbEntityValidationException if there are validation errors. You can then use the exception to add the errors to the ModelState.

如果存在验证错误,实体框架应抛出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);
          }
     }
}

#4


0  

One of the ways to pass the contents of IEnumerate and keep taking advantage of Html.ValidationSummary is by updating ModelState.

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

You can find a good discussion on how to update the ModelState here.

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

#1


11  

Add property, say BusinessError, in the model

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

in the View do the following

在视图中执行以下操作

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

Then in your controller whenever you have error do the following

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

ModelState.AddModelError("BussinessError", your error)

#2


2  

I would have a look at FluentValidation. It's a framework for validation without data annoations. I've used it with great success in some projects for complex validation, and it is also usable outside of the MVC-project.

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

Here is the sample code from their page:

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

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;

#3


1  

Entity Framework should throw a DbEntityValidationException if there are validation errors. You can then use the exception to add the errors to the ModelState.

如果存在验证错误,实体框架应抛出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);
          }
     }
}

#4


0  

One of the ways to pass the contents of IEnumerate and keep taking advantage of Html.ValidationSummary is by updating ModelState.

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

You can find a good discussion on how to update the ModelState here.

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