0
votes

I'm trying to write an AspNet Api using SimpleInjector. However I'm having issues with SimpleInjector. When I start the AspNet application after registering a type in the container, I get this error:

Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Web.Services.WeatherForecastController Lifetime: Transient ImplementationType: Web.Services.WeatherForecastController': Unable to resolve service for type 'MediatR.IMediator' while attempting to activate 'Web.Services.WeatherForecastController'.) ---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Web.Services.WeatherForecastController Lifetime: Transient ImplementationType: Web.Services.WeatherForecastController': Unable to resolve service for type 'MediatR.IMediator' while attempting to activate 'Web.Services.WeatherForecastController'. ---> System.InvalidOperationException: Unable to resolve service for type 'MediatR.IMediator' while attempting to activate 'Web.Services.WeatherForecastController'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)

I understand that there is a missing type not registered in the container, however I register the Mediator just before instantiating the Aspnet server

 public class Program
    {
        public static async Task Main(string[] args)
        {
            var configuration = LoadConfiguration(args);
            var comp = new AspNetComponent(args);
            var container = new Container();
            container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
            container.Options.DefaultLifestyle = Lifestyle.Scoped;
            DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
            container.Register<IMediator, Mediator>();
            comp.Configure(configuration, container);
            await comp.StartAsync(CancellationToken.None);
        }

In AspNetComponent.cs:

 public static IHostBuilder CreateHostBuilder(
      string[] args, IConfiguration configuration, Container container)
        {
            Startup.UseContainer(container);
            return Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.UseUrls("https://0.0.0.0:8080");
                });
        }

And my Startup.cs class:

 public class Startup
    {
        private static Container _container;

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        internal static void UseContainer(Container container)
        {
            _container = container;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
                .AddApplicationPart(
                    Assembly.GetAssembly(typeof(WeatherForecastController)))
                .AddControllersAsServices();

            services.AddSimpleInjector(_container, options =>
            {
                options.AddAspNetCore()
                    .AddControllerActivation();
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseSimpleInjector(_container);
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        }

I have no idea what is the issue, I've been debugging for almost 3 days.

1
I can't reproduce your issue. My advise is to create a new web project using the default VS template, and add Simple Injector's integration as described in the documentation. When that works, add your required features step for step until it breaks.Steven

1 Answers

1
votes

I think your code registers controllers twice (once in default container and second time inside .AddSimpleInjector). Default container comes first and it does not have Mediatr registered (we did it in SimpleInjector container only), therefore it fails when constructs controller - it cant resolve IMediatr. Just remove first case of registering controllers.

public void ConfigureServices(IServiceCollection services)
{
    // comment out first registration of services
    // we keep services.AddMvc() because it is required for simple injector container AddAspNetCore()
    services.AddMvc()
        .AddApplicationPart(Assembly.GetAssembly(typeof(WeatherForecastController)));
        //.AddControllersAsServices();

    // you are doing this in Program.cs
    var container = new Container();

    services.AddSimpleInjector(container, x =>
    {
        x.AddAspNetCore()
            .AddControllerActivation();
        // you are doing this in Program.cs
        x.Container.BuildMediator(Assembly.GetExecutingAssembly());
    });
}