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'.
The Middleware it's referring to is pretty standard.
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()
.
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)
The solution for this problem contains two main elements:
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
.
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;
});