Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET MVC Custom validation (without data annotation)

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):

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:

    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?

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.

Thanks

like image 573
Alex Dn Avatar asked Apr 17 '13 17:04

Alex Dn


2 Answers

Add property, say BusinessError, in the model

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)
like image 168
Dan Hunex Avatar answered Oct 05 '22 15:10

Dan Hunex


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.

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;
like image 45
Tomas Jansson Avatar answered Oct 05 '22 14:10

Tomas Jansson