NancyFx / Nancy

Lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono
http://nancyfx.org
MIT License
7.15k stars 1.46k forks source link

Modify Validation to allow for additional parameters #2282

Open eckersalld opened 8 years ago

eckersalld commented 8 years ago

Currently using the Nancy.FluentValidation library, and would love to use the RuleSets in Fluent, however there is no extension (that I can see!) method to achieve that.

I could just use Fluent directly, but ideally I'd like to keep all my modules following a consistent pattern so anyone doing any changes in the future won't have too steep a learning curve.

ZeVS777 commented 8 years ago

for using Fluent directly I use this method.

    class FluentValidationFactory : IValidatorFactory
    {
        private readonly ConcurrentDictionary<Type, IValidator> cachedValidators;

        private readonly IEnumerable<IValidator> validators;

        public FluentValidationFactory(IEnumerable<IValidator> validators)
        {
            this.validators = validators;
            cachedValidators = new ConcurrentDictionary<Type, IValidator>();
        }

        private static Type CreateValidatorType(Type type)
        {
            return typeof(AbstractValidator<>).MakeGenericType(type);
        }

        public IValidator<T> GetValidator<T>()
        {
            return (IValidator<T>)GetValidator(typeof(T));
        }

        public IValidator GetValidator(Type type)
        {
            return cachedValidators.GetOrAdd(type, CreateValidator);
        }

        private IValidator CreateValidator(Type type)
        {
            var fullType =
                CreateValidatorType(type).GetTypeInfo();

            return validators
                .SingleOrDefault(validator => fullType.IsAssignableFrom(validator.GetType()));
        }
    }
        protected override void ApplicationStartup(IKernel container, IPipelines pipelines)
        {
            base.ApplicationStartup(container, pipelines);
            //Register with Ninject, for example, at the startup in singleton
            container.Bind<IValidatorFactory>().To<FluentValidationFactory>().InSingletonScope();
        }
    public class UserModule: NancyModule
    {
        public UserModule(IValidatorFactory validationFactory) 
        {
            Post["/login"] = _ =>
            {
                var loginUser = this.Bind<LoginUser>();
                var validator = validationFactory.GetValidator<LoginUser>();
                var validationResult = validator.Validate(loginUser, ruleSet: "myset");
                ...