为什么我会收到此 InvalidOperationException:无法解析类型“Microsoft.AspNetCore.Http.RequestDelegate”的服务?

Row*_*man 10 c# .net-core asp.net-core scrutor asp.net-core-3.1

我刚刚将 ASP.NET Core WebApi 项目从 .NET Core 2.2升级到3.1

我已经修复了所有编译时错误,升级了 Nuget 包,现在可以运行该应用程序。

但是,当我调用Build()my时IHostBuilder,出现以下异常:

InvalidOperationException:尝试激活“MyProject.Api.Middleware.ExceptionHandlerMiddleware”时无法解析类型“Microsoft.AspNetCore.Http.RequestDelegate”的服务。

无效操作异常

它所指的中间件是非常标准的。

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序初始化的其余部分是相当标准的,从 2.2 到 3.1 我没有做太多改变(2.2 正在工作)。

我确实从 更改services.AddMvc()services.AddControllers()

程序.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();
            });
    }
}

Run Code Online (Sandbox Code Playgroud)

还值得一提的是,ConfigureServices()中的方法Startup.cs正在被调用并且运行良好,但Configure() 从未运行。该Build()方法总是在应用程序到达之前将其终止Configure()

我的 Startup 的Configure方法签名如下所示:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
Run Code Online (Sandbox Code Playgroud)

use*_*440 7

我今天遇到了同样的问题并解决了如下:

在.net core 2.2中,我将中间件添加到应用程序生成器中,并将中间件添加到服务集合中。显然,不再需要将中间件添加到服务集合中,并会导致您发布的异常。

就我而言,删除该行

services.AddSingleton<MyMiddleware>();
Run Code Online (Sandbox Code Playgroud)

解决了问题。


小智 7

这是对于使用 .netCore 6 的人的答案:

  • 首先删除RequestDelegate的属性:
 private readonly RequestDelegate _next;
Run Code Online (Sandbox Code Playgroud)
  • 然后删除RequestDelegate的构造函数:
public SomeClassName (RequestDelegate next)
{
   _next = next;
}

Run Code Online (Sandbox Code Playgroud)
  • 最后,这是 Invoke 方法:
 public class SomeMiddleware : IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            Console.WriteLine("Hi I am Middleware in .net6");
            await next(context);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Row*_*man 5

该问题的解决方案包含两个主要要素:

  1. .NET Core 3.0 引入了有关服务提供程序验证的更改。
  2. 我的代码注册了太多类,导致验证失败。

我的问题的解决方案是在中引入以下代码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)
        })
        [ ... ]
}
Run Code Online (Sandbox Code Playgroud)

感谢其他答案将我的注意力引向我的Startup.cs.

完整解释

我使用Scrutor扫描程序集并自动注册类。Scrutor 正在查找并注册我的中间件类,例如ExceptionHandlerMiddleware.

它在 .NET Core 2.2 和 3.1 中都是这样做的。那么为什么它只在 Core 3.1 中出现呢?

因为.NET Core 3.0 引入了通用主机作为构建主机的新默认方式。

代码现在包含ValidateOnBuild在开发环境下默认启用的部分。这导致我的 ServiceProvider 在构建时进行验证。它无法解决,RequestDelegate因为我没有注册。

.UseDefaultServiceProvider((context, options) =>
{
    var isDevelopment = context.HostingEnvironment.IsDevelopment();
    options.ValidateScopes = isDevelopment;
    options.ValidateOnBuild = isDevelopment;
});
Run Code Online (Sandbox Code Playgroud)