8

I've just upgraded my ASP.NET Core WebApi project from .NET Core 2.2 to 3.1.

I've fixed up all of the compile-time errors, upgraded my Nuget packages, and I can now run the app.

However, When I call Build() on my IHostBuilder, I get the following exception:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'MyProject.Api.Middleware.ExceptionHandlerMiddleware'.

InvalidOperationException

The Middleware it's referring to is pretty standard.

ExceptionHandlerMiddleware.cs

public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlerMiddleware> _logger;

    public ExceptionHandlerMiddleware(RequestDelegate next, ILogger<ExceptionHandlerMiddleware> logger)
    {
        _logger = logger;
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        // redacted
    }
}

The rest of my app initialisation is fairly standard and I didn't change much going from 2.2 to 3.1 (2.2 was working).

I did change from services.AddMvc() to services.AddControllers().

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    private static IHostBuilder CreateHostBuilder(string[] args)
    {
        return Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(builder =>
            {
                builder.UseSerilog().UseStartup<Startup>();
            })
            .ConfigureLogging((context, logging) =>
            {
                logging
                .AddConfiguration(context.Configuration.GetSection("Logging"))
                .AddConsole()
                .AddDebug();
            });
    }
}

It's also worth mentioning that the ConfigureServices() method in Startup.cs is being called and runs fine, but Configure() never runs. The Build() method always kills the app before it gets to Configure().

My Startup's Configure method signature looks like this:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
Rowan Freeman
  • 15,724
  • 11
  • 69
  • 100

4 Answers4

7

I ran into the same problem today and resolved it as follows:

In .net core 2.2 I added the middleware to the application builder and also added the middleware to the service collection. Apparently adding the middleware to the service collection is no longer required and results in the exception you posted.

In my case removing the line

services.AddSingleton<MyMiddleware>();

resolved the issue.

user1796440
  • 366
  • 3
  • 11
4

The solution for this problem contains two main elements:

  1. .NET Core 3.0 introduced a change regarding service provider validation.
  2. My code is registering too many classes, causing the validation to fail.

The solution to my problem was to introduce the following code in Program.cs:

private static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .UseDefaultServiceProvider(opt =>
        {
            // this overrides the default service provider options
            // so that it doesn't validate the service collection (which raises exceptions)
        })
        [ ... ]
}

Thanks to other answers that directed my attention to my Startup.cs.

Full explanation

I use Scrutor to scan assemblies and auto-register classes. Scrutor is finding and registering my Middleware classes such as ExceptionHandlerMiddleware.

It was doing this in .NET Core 2.2 as well as 3.1. So why did it only break in Core 3.1?

Because .NET Core 3.0 introduced the Generic Host as the new default way to build a host.

The code now contains a part to enable ValidateOnBuild by default under the development environment. This caused my ServiceProvider to validate on build. And it couldn't resolve RequestDelegate because I didn't register that.

.UseDefaultServiceProvider((context, options) =>
{
    var isDevelopment = context.HostingEnvironment.IsDevelopment();
    options.ValidateScopes = isDevelopment;
    options.ValidateOnBuild = isDevelopment;
});
Rowan Freeman
  • 15,724
  • 11
  • 69
  • 100
4

Here is the answer for those who use .netCore 6 :

  • First Remove Property of RequestDelegate :
 private readonly RequestDelegate _next;
  • And then remove Your Constructor for RequestDelegate :
public SomeClassName (RequestDelegate next)
{
   _next = next;
}

  • finally , here is the Invoke method :
 public class SomeMiddleware : IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            Console.WriteLine("Hi I am Middleware in .net6");
            await next(context);
        }
    }
3

As @user1796440 said,I could reproduce your issue by using services.AddSingleton<MyMiddleware>();.

To fix it,you need register middleware like below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseMiddleware<ExceptionHandlerMiddleware>();
    //...
}
Rena
  • 30,832
  • 6
  • 37
  • 72
  • I thought about that, but the problem is that my `Configure()` method is never called. The exception is thrown earlier, so I would never get to this point of `UseMiddleware()`. – Rowan Freeman Dec 26 '19 at 10:17
  • So could you share your Startup.cs?It would be more helpful to resolve your issue. – Rena Dec 27 '19 at 01:28