Fluent Validation Model Binder – Asp.net MVC

A few weeks ago I found the Fluent Validation framework by Jeremy Skinner. I needed to conditionally validate a model depending on an application setting. eg. Description field mandatory / not mandatory depending on the clients business requirements. I loved the simplicity of the framework and the separation from the model it provided.

Since then I have submitted a few patches for the framework, one of which is the Fluent Validation Model binder. Inspired by the Data Annotations Model binder, it works in much the same way. Once you have it set to your default model binder, it will validate any model which contains the specific attribute. This will become clear in the examples below.

Firstly lets take our model.


    [Validator(typeof(LineItemValidator))]
    public class LineItem
    {
        public int LineNumber { get; set; }
        public DateTime Date { get; set; }
        public string Description { get; set; }
        public decimal Net { get; set; }
        public decimal Tax { get; set; }
        public decimal Gross { get; set; }
    }

Attached to this simple LineItem class is a Validator attribute. This attribute is used by the Model Binder to locate the Class used for validation. Below I will define my LineItemValidator class which will hold the rules for the validation.


public class LineItemValidator : AbstractValidator<LineItem> { public LineItemValidator() { RuleFor(x => x.Description) .NotEmpty().When(x => Settings.DescriptionRequired) .And .Length(0, 30); RuleFor(x => x.Date) .GreaterThanOrEqualTo(DateTime.Today); RuleFor(x => x.Net) .GreaterThan(0); RuleFor(x => x.Gross) .GreaterThan(0) .And .Equal(y => (y.Net + y.Tax)) .WithName("Total Amount"); } }

As you can see the class must inherit from AbstractValidator<T> where T is the model you want to define the rules for. The first rule uses the conditional When clause where it will only validate that the field is NotEmpty when the Settings.DescriptionRequired boolean is true. Also, another thing is the complex validation taking place on the Gross field. Not only does it validate that it is greater than 0, but that the value is equal to the net + tax amount. This is very elegant indeed. I have also specified the ‘WithName’ clause which has also been integrated into the model binder so that if an error occurs with the gross field, the WithName value will be displayed when an error happens. This is extremely handy for language localization or when the name of the field on the Model is insufficient.

Wiring this Model binder up in the Application_start event in the global.asax.cs is as easy as this.


ModelBinders.Binders.DefaultBinder = new FluentValidationModelBinder(new AttributedValidatorFactory());

Note that we have to pass an instance of the AttributedValidatoryFactory into the Model Binder. This means if you have an alternate way of locating the Validator class other than via the attribute you can inherit from IValidatorFactory and create your own.

Now when a parameter of LineItem gets passed into a controller it will be validated against the model and all errors placed into the ModelState. This can then check the isValid property to determine if there are any errors and proceed accordingly.


        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(List<LineItem> lineItems)
        {
            if (ModelState.IsValid)
                return RedirectToAction("Edit");

            return View();
        }

And that’s it. I hope you enjoy using the Fluent Validation framework as much as I have and happy coding. For all you guys waiting for xVal integration, I will try and post a solution in the coming week.

Adam

10 Responses to Fluent Validation Model Binder – Asp.net MVC

  1. CitizenBane says:

    If I attach a validator to an entity, and it contains a collection of other entities with validators, I end up with a double entry on the ModelState errors.

  2. Wow this worked great.. Cheers. I’d liek to thank you for you’r work on fluentvalidatin and xVal it’s a stack I’ve really liked the look of glad you put the patches in place to make it work.

    One quick question.

    I get a message saying FluentValidationModelBinder Depricated how would you update this to use the new FluentValidationModelValidatorProvider. Would this be done in the controllers them selves?

    Thanks again sorry if this is a dumb question just I’m a noob ;)

  3. Bob says:

    Hello, Adam…

    Can you send me the solution, please?

    Regards…

  4. [...] This post was mentioned on Twitter by Hire ASP.Net Experts, Murat. Murat said: Fluent Validation Model Binder – Asp.net MVC http://bit.ly/bpkDFf [...]

  5. Bryan Shen says:

    This looks really nice!! Thanks.

  6. Hari says:

    Hey, This is great.. I started using it but ran across a problem real quick.

    In case of String, int etc .. the model binding is working great. But if i have some custom object in my class, the binding does not work.

    In my entities, I have something like

    public virtual Quotation_Products Prd { get; set; }

    From the view when I set Html.TextBox(“Prd.Product_Id”), I get a Null Pointer exception.

    If I removed the Fluent validator model binding from the global.asax, the binding works, but ofcourse the validations dont fire. Is there a fix to this?

  7. Schotime says:

    Make sure you are using the latest version from http://fluentvalidation.codeplex.com/

  8. Ian says:

    So where is the code for FluentValidationModelBinder?

  9. Schotime says:

    Its part of FluentValidation.Mvc

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>