Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentValidation, Validators lifecycle and using Validators to check against Db

I'm using FluentValidation in my MVC4 project. Every thing works perfectly and it's connected to my IoC (StructureMap).

I have 2 questions:

  1. How should I manage lifecycle of my validators? Is it ok to make them singleton? or it makes no difference and I can manage lifecycle according to my needs? What is the best practice here?

  2. FluentValidation is very good. I have been using it for simple validations (like: property is not empty, etc.). I'm thinking about doing some Db validations using it(like: property value is unique.) I can pass my repository to it using StructureMap and check values against Db. Is this a good idea? or should I implement this logic in my service layer and not in my IValidator?

If you used it in similar scenarios, what was your experience?

like image 867
Afshin Gh Avatar asked Jun 09 '13 00:06

Afshin Gh


3 Answers

I've used FluentValidation for years now and have asked and figured out your questions.

  1. Personally the cost of creating a validator is not very expensive, so I do not make them singletons. I've run into issues with Singletons that required access to the HttpContext to require a file upload. What happens is the first HttpContext is always used in the validation rather than the current one.

I personally recommend you DON'T use singletons.

  1. I actually do this all the time and I like it. Just be mindful that any dependency you inject should be efficient. If your database query does a full table scan and takes 30 seconds, then that isn't a good experience. Like I said above, I usually inject HttpContext to check if files were uploaded, and I pass a DataContext to validate an email isn't already taken.

Go crazy with this, it is a huge advantage of FluentValidation, just make sure the dependency isn't expensive in regards to time and resources.

like image 200
Khalid Abuhakmeh Avatar answered Oct 21 '22 02:10

Khalid Abuhakmeh


I have just been looking into this myself using unity and MVC 4.

What I have seen is that if you keep them as Transient objects. FluentValidation will create a new validation object for every property that is been validated. So some caching is required.

For my caching I have looked at Per Request caching of the validator. This works well as all the dependent components are Per Request. (Per Request is custom code which stores a child Unity Container on the HttpContext.Current.Items collections with a HTTP module that destroys/dispose the Child Container at the end of the request)

To choose between Per Request and Singleton instants of the validator comes down to how your using it and what type of dependencies it has and the capablities of the IoC Continer.

With unity you can create a singleton validator and inject the service factory using a function ie Func serviceFunc.

In my case each time I call the serviceFunc, the Unity ChildContiner 'service' is retrieved. Thus I can still have my 'validator' defined with a ContainerControlledLifetimeManager(singleton) and have the 'service' defined with HierarchicalLifetimeManager(Per Request).

A downside of this is each time the serviceFunc is invoked it needs to check and retrieves the service from the child container. This will be the most likely reason why I will do back to 'per request')

I have just updated my code to use serviceFunc and will test it today. I believe it will be trial an error to find the correct solution for your aplications.

Below is the validtion factory I'm using - instead of using the unity container (as most examples on the web do), I'm injecting the IDependencyResolver into it and using that to resolve my validator objects.

public class ValidatorFactory : IValidatorFactory 
{
    private readonly IDependencyResolver _dependencyResolver;

    // taken from the attribute Validation factory
    public ValidatorFactory(IDependencyResolver dependencyResolver)
    {
        _dependencyResolver = dependencyResolver;
    }

    /// <summary>
    /// Gets a validator for the appropriate type.
    /// 
    /// </summary>
    public IValidator<T> GetValidator<T>()
    {
        return (IValidator<T>)this.GetValidator(typeof(T));
    }

    /// <summary>
    /// Gets a validator for the appropriate type.
    /// 
    /// </summary>
    public virtual IValidator GetValidator(Type type)
    {
        if (type == (Type)null)
            return (IValidator)null;
        var validatorAttribute = (ValidatorAttribute)Attribute.GetCustomAttribute((MemberInfo)type, typeof(ValidatorAttribute));
        if (validatorAttribute == null || validatorAttribute.ValidatorType == (Type) null)
        {
            return (IValidator) null;
        }
        else
        {
            return _dependencyResolver.GetService(validatorAttribute.ValidatorType) as IValidator;
        }
    }
}
like image 22
Edys Avatar answered Oct 21 '22 01:10

Edys


Validation is unsurprisingly a complex and usually depends on the architecture for your application, but here are my thoughts.

  1. Validators should be managed according to your needs. I would typically leave static class instances to typically serving infrastructure concerns like factories or object builders.

  2. Without doubt the FluentValidation library is great. Typical problems faced by validation are not a result of the library you choose but the way in which validation is applied. In most typical application validation of an object / entity / domain is contextual, whereby validation depends completely on the context of the operation you’re trying to perform. For example validation on the same object is likely to be different for persistence, changing an attribute, changing state, for ETL, etc. Keeping all of this in mind I believe that validation belongs as close to the operation being performed as possible.

Hopefully this helps.

like image 44
Kane Avatar answered Oct 21 '22 01:10

Kane