question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Issue] Creating Duplicate Services on FluentValidator Startup Registration

See original GitHub issue

System Details

  • FluentValidation version: aspnetcore & DependencyInjectionExtensions 8.6.1
  • Web Framework version: dotnet core 3.1

Issue Description

So I have the attached startup and validator files which, on the surface, work fine when running my API:

FV_PetStartup.txt FV_PetValidators.txt

The Issue

My issue is, when I run a simple integration test like this:

        [Fact]
        public async Task PostPetReturnsSuccessCodeAndResourceWithAccurateFields()
        {
            // Arrange
            var client = _factory.CreateClient();
            var fakePet = new FakePetDto().Generate();

            // Act
            var httpResponse = await client.PostAsJsonAsync("/v1/Pets", fakePet)
                .ConfigureAwait(false);

            // Assert
            httpResponse.EnsureSuccessStatusCode();

            var resultDto = JsonConvert.DeserializeObject<PetDto>(await httpResponse.Content.ReadAsStringAsync()
                .ConfigureAwait(false));

            httpResponse.StatusCode.Should().Be(201);
            response.Should().ContainEquivalentOf(fakePet);
        }

It is throwing this error:

System.InvalidOperationException: ‘Sequence contains more than one matching element’

My Findings So Far

I know fluent validators is the issue because I can comment out my validators registration in startup and the integration test doesn’t throw the error anymore.

I dug into it and, as far as I can tell, the configureservices method in my startup is creating duplicate validator services, which would make sense given the error message. I’ve tried numerous iterations of fluent validator registrations on addmvc:

//.AddFluentValidation(fv =>
            //{
            //    //fv.RegisterValidatorsFromAssemblyContaining<PetForManipulationDtoValidator>();
            //    //fv.RegisterValidatorsFromAssemblyContaining<PetForUpdateDtoValidator>();
            //    fv.RegisterValidatorsFromAssemblyContaining<PetForCreationDtoValidator>();
            //});
            //.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblies(AppDomain.CurrentDomain.GetAssemblies()));
            //RegisterValidatorsFromAssemblyContaining<StartupDevelopment>());

None of which have worked, even a simple breakdown with just one abstract validator. Hoping some fresh eyes can see what I’m missing.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:20 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
JeremySkinnercommented, Feb 29, 2020

Ok, I’ve spent a few hours on this and I’ve not really been able to get any further than where you did. Understanding the complex interactions between WebApplicationFactory and the WebHost factory is probably better left up to the asp.net team to troubleshoot. But we can definitely be certain the double startup isn’t related to FluentValidation or any other 3rd party component.

I’m not sure why FV FluentValidationModelValidatorProvider is the only thing that gets duplicated

This is because the FV provider is not being registered as a service. The services registrations are being overwritten/recreated when ConfigureServices runs the second time, but the FVModelValidatorProvider is being added to the ModelValidatorProviders collection as part of a call to AddMvcOptions (see https://github.com/FluentValidation/FluentValidation/blob/master/src/FluentValidation.AspNetCore/FluentValidationMvcExtensions.cs#L66-L80) Because the MvcBuilder is the same instance across both calls to ConfigureServices, the configuration logic ends up being registered twice (and run twice).

What I’ve done is add a check if the provider has been added to the collection already and skip registering again (7776bff1383299a404b4a612d84fe399f92cb21b). We shouldn’t really have to do this, but works around the problem until MS fix it in core. This will be part of 9.0 (I’ll try and push out a 9.0-preview3 either later today or tomorrow)

Anyway, at least you have a workaround for now.

1reaction
JeremySkinnercommented, Feb 26, 2020

Ok, thanks. I’m planning to spend a couple of hours working on FluentValidation on Friday, so I’ll try and dig into this then.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - FluentValidation: How to register all validators ...
Registering each validator in Service with AddTransient. ... If you use option number 2 and replace Startup in your code with any class ......
Read more >
Duplicate Validation Messages with FluentValidation in ASP ...
If you used this in an ASP.NET Core 5 MVC project and forgot to complete the Name , you would see the following...
Read more >
Using Fluent Validation in ASP.NET Core
Fluent Validation is a free-to-use .NET validation library that helps you make your validations clean, easy to create, and maintain.
Read more >
Creating Complex Validation Rules Using Fluent ...
A recipe for complex validation requirements. This recipe will demonstrate how to use the Fluent Validation package to solve the above problem.
Read more >
Built-In, Nested, Custom Validators with FluentValidation
This will register the OrderValidator class we created previously with FluentValidation, and make sure FluentValidation runs on all requests ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found