Please post questions and issues on Github:

https://github.com/vanthoainguyen/NValidator/issues

 

 

 

In order to use NValidator, we should download NValidator nuget package into the project using Nuget. If you are new to Nuget, please follow this link to find out how to use Nuget.

After having NValidator referenced in the project, we need to create the validator class for the business object. There are 2 type of validators: TypeValidator and CompositeValidator. Given that we have 2 classes: User and Address. There are UserValidator and AddressValidator registered as the default validators using ValidatorFactory static class. If we perform validation on an User instance using UserValidator, it will not perform validation on the nested Address object if the UserValidator inherit from TypeValidator. And in contrast, if the UserValidator inherits from CompositeValidator, the AddressValidator which was registered as default will be automatically resolved and used to validate the nested Address object when the User instance is validated.

For example, imagine that we have the Address and User class below:

    public class Address
    {
        public string Number { get; set; }
        public string Street { get; set; }
        public string PostCode { get; set; }
        public string Suburb { get; set; }
        public string Country { get; set; }
    }

    public class User
    {
        public string Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        public string Title { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }

        public Address Address { get; set; }
    }

We can define the validation logics for those classes by either inheriting from TypeValidator<T> or ComositeValidator<T>:

    public class AddressValidator : TypeValidator<Address>
    {
        public AddressValidator()
        {
            RuleFor(address => address.Number)
                .Match(@"[\w\d]+");

            RuleFor(address => address.Street)
                .Match(@"[\w\d]{1, 200}");

            RuleFor(address => address.PostCode)
                .StopOnFirstError()
                .Length(4, 5)
                .Match(@"\d]{4, 5}")
                .AllWithMessage(address => string.Format("'{0}' is not an valid postcode.", address.PostCode));

            RuleFor(address => address.Suburb)
                .StopOnFirstError()
                .NotNull()
                .NotEmpty();

            RuleFor(address => address.Country).Must(BeACountry);

        }

        private static bool BeACountry(string country)
        {
            // ..... Code to check country here
        }
    }


    public class UserValidator : CompositeValidator<User>
    {
        public UserValidator()
        {
            RuleFor(user => user.Id)
                .NotEmpty()
                .NotNull();

            RuleFor(user => user.UserName)
                .NotNull()
                .Length(6, 10)
                .Must(x => !x.Contains(" ")).WithMessage("@PropertyName cannot contain empty string.");

            RuleFor(user => user.Password)
                .StopOnFirstError()
                .NotEmpty()
                .Length(6, 20)
                .Must(x => x.Any(c => c >= 'a' && c <= 'z') &&
                           x.Any(c => c >= '0' && c <= '9') &&
                           x.Any(c => c >= 'A' && c <= 'Z')).WithMessage("@PropertyName must contain both letter and digit.");

            RuleFor(user => user.Title)
                .In("MR", "MS", "MRS", "DR", "PROF", "REV", "OTHER");

            RuleFor(user => user.FirstName)
                .NotEmpty().WithMessage("Please specify the first name.");

            RuleFor(user => user.LastName)
                .NotEmpty().WithMessage("Please specify the last name.");
            
            RuleFor(user => user.Email)
                .Email();
        }
    }

Then we should register those validators using ValidatorFactory:

    ValidatorFactory.Current.Register<AddressValidator>(true /* AddressValidator will be resolved in any CompositeValidator*/);
    ValidatorFactory.Current.Register<UserValidator>();      /* UserValidator won't be resolved in any CompositeValidator*/

That also means AddressValidator will be returned when we call ValidatorFactory.Current.GetValidatorFor<Address>() and UserValidator won't be returned when we do the same thing with type User. However, we still can retrive the validator by using method ValidationFactory.Resolve<UserValidator>(). I'll write more about the way ValidatorFactory work in other topic.

The default implementation of ValidatorFactory uses in-memory caches to store all the registered types and instances of validators. It can be replaced anytime in your application bootstrapper by changing the ValidatorFactory.Current value by a custom implementation of IValidatorFactory using StructureMap, Autofac or whaterver. There is just one thing to keep in mind when implementing a custom ValidatorFactory: any validators which are registered as default will be resolved and used to validate in a composite validadator. If you just want to use TypeValidator, that's fine because NValidator supports creating rules for any nested Type include Array access.

As you can see in the validators above, the way to register the rules is pretty straightforward. As I described on the home page, the fluent syntax is inspired from the well-known Fluent Validation library. NValidator currently supports most of the popular rules. Well I reinvent the wheel just because I want to keep myself busy and in the other hand, I'm gonna use NValidator in my validation heavy WCF project. Therefore, NValidator hasn't supported MVC yet but I hope I can do that after finishing the documentation. To be honest, I spent my spare time during last week to write the code and the page you are reading :D.

Please navigate to other Wiki pages for more details about the library and advanced topics.

Cheers.

Last edited Aug 20, 2014 at 11:17 AM by nvthoai, version 7

Comments

nvthoai Aug 20, 2014 at 11:23 AM 
I'm sure there is.

This project hasn't been maintained for more than 2 years but I think it's open enough to extend.

Feel free to post your further questions on Github https://github.com/vanthoainguyen/NValidator/issues


Thanks

Patrick13 Apr 10, 2014 at 7:58 PM 
Is there any way to register multiple validators for a class/model and then choose which one to use? I am thinking about using this but need to support multi-tenant architecture.

Also does this library support i18n like Fluent Validation?