IoC container issue with .NET 8, minimal api, and MediatR 12.2.0

149 Views Asked by At

I have a minimal API project where I am using the MediatR v12.2.0. The code works fine when I debug using Visual Studio 2022, however, I am not able to get the code deployed to docker. In docker, once the app runs, I see the following messages in the logs.

2024-01-31 17:56:50 Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IMediator Lifetime: Transient ImplementationType: MediatR.Mediator': A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.) 
2024-01-31 17:56:50  ---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: MediatR.IMediator Lifetime: Transient ImplementationType: MediatR.Mediator': A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor. 
2024-01-31 17:56:50  ---> System.InvalidOperationException: A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor. 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache, ServiceIdentifier, Type , CallSiteChain) 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor, ServiceIdentifier, CallSiteChain, Int32) 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor, CallSiteChain) 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor) 
2024-01-31 17:56:50    --- End of inner exception stack trace --- 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor) 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection``1, ServiceProviderOptions) 
2024-01-31 17:56:50    --- End of inner exception stack trace --- 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection``1, ServiceProviderOptions) 
2024-01-31 17:56:50    at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection, ServiceProviderOptions) 
2024-01-31 17:56:50    at Microsoft.Extensions.Hosting.HostApplicationBuilder.<>c__DisplayClass12_0.<.ctor>b__0() 
2024-01-31 17:56:50    at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build() 
2024-01-31 17:56:50    at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() 
2024-01-31 17:56:50    at Program.<Main>$(String[]) in /app/apis/services/Pique.Services/Program.cs:line 119 
2024-01-31 17:56:50    at Program.<Main>(String[])

I tried using the following two methods to register the MediatR in the IoC container.

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
builder.Services.AddMediatR(config => { config.RegisterServicesFromAssemblyContaining<Program>(); });

But I still keep seeing the same error message. Does that message mean that .NET is not able to resolve to a concrete instance of the IMediator? This did work back in .NET 6. I simply upgraded the .net version to 8 and upgraded the referenced libraries in Visual Studio and started seeing this when I deploy to docker.

Below is my program.cs file:

using Dapper.FluentMap;
using Microsoft.OpenApi.Models;
using Pique.Common.Exceptions;
using Pique.Services.Endpoints;
using Pique.Services.Handlers.DoloDocs;
using Pique.Services.Middleware;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Register MediatR
//builder.Services.AddMediatR(config => {
//    config.RegisterServicesFromAssembly(typeof(Pique.Services.AutoMapperProfile).Assembly);
//});
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(Program).GetTypeInfo().Assembly));

// Register Automapper
builder.Services.AddAutoMapper(config =>
{
    config.AddProfile<Pique.Services.AutoMapperProfile>();
});


var app = builder.Build();

app.UseCors();

// Add global exception handler
app.UseMiddleware<ExceptionMiddleware>();

// Add claims middleware - Used for Authentication & Authorization
app.UseMiddleware<ClaimsMiddleware>();

// Add request logging middleware
app.UseMiddleware<Pique.Common.RequestLoggerMiddleware>();

// Use Swagger UI to display the documentation
app.UseSwagger();
app.UseSwaggerUI(o =>
{
    o.DefaultModelsExpandDepth(-1);
});


await app.RunAsync();

And here's my Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env

EXPOSE 8080

# copy api project
COPY /apis/services/Services/ ./apis/services/Services/

# build out the solution
WORKDIR /app/apis/services/Services
RUN dotnet restore
RUN dotnet publish -c Release --self-contained true /p:PublishTrimmed=true -o /out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
COPY --from=build-env /out .

ENTRYPOINT ["dotnet", "Services.dll"]
0

There are 0 best solutions below