[Issue] Creating Duplicate Services on FluentValidator Startup Registration
See original GitHub issueSystem 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:
- Created 4 years ago
- Comments:20 (11 by maintainers)
Top GitHub Comments
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.
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 toAddMvcOptions
(see https://github.com/FluentValidation/FluentValidation/blob/master/src/FluentValidation.AspNetCore/FluentValidationMvcExtensions.cs#L66-L80) Because theMvcBuilder
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.
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.