ASP.NET MVC3 Fluent Validation Constructor hit multiple times per request
Asked Answered
T

2

6

I have an ASP.NET MVC3 website setup using fluent validation and ninject. The validation code is working. However, I set a break point in the validation class constructor and I noticed that when I request my view that uses the validation the constructor gets hit multiple times. Based on very basic testing it seems that the number of times the constructor is hit is equal to the number of properties that exist on the object. Has anyone else come across something similar? Or can someone shed more insight on how this type of validation works behind the scenes? -Thanks

Here is the constructor...

public class PersonValidator : AbstractValidator<Person> {
    public PersonValidator() {
        RuleFor(x => x.Id).NotNull();
        RuleFor(x => x.Name).Length(0, 10);
        RuleFor(x => x.Email).EmailAddress();
        RuleFor(x => x.Age).InclusiveBetween(18, 60);
    }
}

Here are the libraries/resources that I am using (I just got the NuGet packages and configured everything based on the info from the two links below):

http://fluentvalidation.codeplex.com/wikipage?title=mvc https://github.com/ninject/ninject.web.mvc.fluentvalidation

Thermoelectrometer answered 18/10, 2011 at 15:53 Comment(3)
Interesting question, do you know what exactly is happening when you call (x => x.Id)? I'm still new to LINQ expressions but I guess this might have something to do with your problemAsparagus
@CodeRush RuleFor(x => x.Id) means to make a rule for the Id property of Person x. @Thermoelectrometer how are you setting up the validator?Liechtenstein
I am familiar with Linq and I also use the fluent api with EF Code First. @Liechtenstein - I added links to the websites that I used to configure my site. I cannot really go through all of the steps, but I can say that I did get the validation to work by following the steps. I would just like to know why that code gets hit so many times. It's concerns me a little. :)Thermoelectrometer
T
4

I figured out how to prevent this issue. Even though this solves my issue, I would like input from others on whether there are any consequences in doing this?

So on the second link you will see instructions on how to set up Ninject.

On the second step you need to apply the "InRequestScope()" extension method. Then the constructor will only be hit once per http request that uses your validator. That obviously means that only one instance of the validator object is created per http request, which makes sense to me. I don't know if there are any consequences to using this solution?

Bind(match.InterfaceType).To(match.ValidatorType).InRequestScope();
Thermoelectrometer answered 21/10, 2011 at 2:8 Comment(0)
D
0

Resurrecting this thread.

I had the same problem with SimpleInjector. My solution was include LifeTime.Scoped on the collection register.

private static void WarmUpMediatrAndFluentValidation(this Container container)
    {
        var allAssemblies = GetAssemblies();

        container.RegisterSingleton<IMediator, Mediator>();
        container.Register(typeof(IRequestHandler<,>), allAssemblies);

        RegisterHandlers(container, typeof(INotificationHandler<>), allAssemblies);
        RegisterHandlers(container, typeof(IRequestExceptionAction<,>), allAssemblies);
        RegisterHandlers(container, typeof(IRequestExceptionHandler<,,>), allAssemblies);

        //Pipeline
        container.Collection.Register(typeof(IPipelineBehavior<,>), new[]
        {
            typeof(RequestExceptionProcessorBehavior<,>),
            typeof(RequestExceptionActionProcessorBehavior<,>),
            typeof(RequestPreProcessorBehavior<,>),
            typeof(RequestPostProcessorBehavior<,>),
            typeof(PipelineBehavior<,>)
        });
        
        container.Collection.Register(typeof(IRequestPreProcessor<>), new[] {typeof(EmptyRequestPreProcessor<>)});
        container.Collection.Register(typeof(IRequestPostProcessor<,>), new[] {typeof(EmptyRequestPostProcessor<,>)});

        container.Register(() => new ServiceFactory(container.GetInstance), Lifestyle.Singleton);

        container.Collection.Register(typeof(IValidator<>), allAssemblies, Lifestyle.Scoped);
    }

container.Collection.Register(typeof(IValidator<>), allAssemblies, Lifestyle.Scoped); <- Workers fine for me, calling only once per request.

Delsiedelsman answered 19/5, 2021 at 15:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.