.NET Core 5 中间件 InvokeAsync 未触发
.NET Core 5 middleware InvokeAsync not triggered
我有一个使用 .NET Core 2.2 中间件的后端解决方案,我将其更新为 .NET Core 5,但不再触发 InvokeAsync
方法。
这是我的代码:
启动(在配置服务中):
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
有效路由中间件:
public class ValidRouteMiddleware
{
private readonly ILogger<ValidRouteMiddleware> _logger;
private const string BadRouteErrorMessage = "Hello World d~.~b";
private readonly RequestDelegate _next;
private readonly List<string> _allRoutes;
public ValidRouteMiddleware(RequestDelegate next, ILogger<ValidRouteMiddleware> logger,
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_next = next;
_logger = logger;
....
}
public async Task InvokeAsync(HttpContext context)
{
if (!MiddlewareTools.CheckRoute(context,_allRoutes))
{
_...
return;
}
else
{
await _next.Invoke(context);
}
}
}
CheckIdChantierDefaultMiddleware:
public class CheckIdChantierDefaultMiddleware
{
private readonly ILogger<CheckIdChantierDefaultMiddleware> _logger;
private const string UnauthorizedErrorMessage = "Non autorisé";
private readonly RequestDelegate _next;
private readonly List<string> _excludedRoutes;
public CheckIdChantierDefaultMiddleware(RequestDelegate next, ILogger<CheckIdChantierDefaultMiddleware> logger,
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_next = next;
...
}
public async Task InvokeAsync(HttpContext context, ComInDbContext dbContext)
{
}
}
等...
缺少什么?
此致
注:整个Startup/ConfigureServices
public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime, IWebHostEnvironment env, ILogger<Startup> logger)
{
Logger = logger;
Logger.LogInformation($"Environnement d'exécution : {Environment.EnvironmentName}");
appLifetime.ApplicationStarted.Register(OnApplicationStarted);
appLifetime.ApplicationStopping.Register(OnApplicationStopping);
appLifetime.ApplicationStopped.Register(OnApplicationStopped);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
// Pour la génération des PDFs, on doit injecter la lib en 32 ou 64
var wkHtmlToPdfContext = new CustomAssemblyLoadContext();
var architectureFolder = (IntPtr.Size == 8) ? "64 bits" : "32 bits";
// Folder dans Infrastructure.PDF
var wkHtmlToPdfPath = Path.Combine(AppContext.BaseDirectory, $"libwkhtmltox\{architectureFolder}\libwkhtmltox");
wkHtmlToPdfContext.LoadUnmanagedLibrary(wkHtmlToPdfPath);
app.UseRouting();
// Utilisation de la règle du CORS
Logger.LogInformation($"Application de la règle `{filteredOrigin}` pour le CORS");
app.UseCors(filteredOrigin);
// Swagger uniquement en DEV
if (Environment.EnvironmentName == "Development" || Environment.EnvironmentName == "PreProduction")
{
// Active Swagger
Logger.LogInformation($"Activation de Swagger (sur l'URL \"/swagger\") ...");
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Swagger - Administration API");
c.RoutePrefix = String.Empty;
});
}
// Active les signaux de HealthCheck sur l'url de routage "/health"
Logger.LogInformation($"Activation des HealthCheck (sur l'URL \"/health\") ...");
// Active le pipeline d'Endpoints
Logger.LogInformation($"Activation du pipeline d'Endpoints ...");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHealthChecks("/health",
new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
var result = JsonSerializer.Serialize(
new
{
status = report.Status.ToString(),
errors = report.Entries.Select(e => new { key = e.Key, value = Enum.GetName(typeof(HealthStatus), e.Value.Status) })
});
context.Response.ContentType = MediaTypeNames.Application.Json;
await context.Response.WriteAsync(result, context.RequestAborted);
}
});
});
app.UseHttpsRedirection();
#region Middleware
// Active le middleware pour la vérification des headers
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
#endregion Middleware
}
我在这里写了一个简单的demo。首先我在startup
中的Configure
方法中创建了一个自定义中间件并在endpoint
之前注册了它,然后你可以看到InvokeAsync触发成功
当我在 endpoint
之后注册中间件时,InvokeAsync 不会被触发。
Panagiotis Kanavos 已经解释了 Endpoint
或者您可以阅读 this 关于路由 Asp .net core 5
我怀疑这段代码是否在 .NET Core 2 中有效。中间件按照请求的注册顺序阻止处理请求。 ASP.NET Core 中的所有内容都是一个中间件块,包括 HTTPS、身份验证、CORS、控制器支持、路由、端点,端点充当中间件链中的 last 步骤。
永远不会调用端点之后注册的任何内容。这包括自定义中间件 和 HTTPS 重定向步骤。
ASP.NET Core middleware page in the docs explains how middleware works and the correct middleware order
至少你需要在 if (env.IsDevelopment())
块之后放置 UseHttpsRedirection
,并在 UseEndpoints
.
之前注册你的自定义中间件
我建议创建一个新的 ASP.NET 核心 MVC 应用程序并检查代码。中间件的顺序已经正确。
.NET Core LTS 版本
您还应该考虑跳过 .NET 5 并直接进入 .NET 6。.NET 5 是一个短期版本,达到 End-Of-Life in May 2022。 Long-Term-Support 版本为 .NET 6,将支持到 2024 年 11 月。
从 .NET 5 迁移到 .NET 6 可能就像将目标从 net6.0
更改为 net5.0
并升级 NuGet 包一样简单。另一方面,从新的最小 MVC 模板开始可以显着减少启动代码,从而减少出现此类错误的机会。
再次尝试创建一个新的空 MVC 网络应用程序并检查生成的代码。
middleware doc page 显示了一个 .NET 6 示例,其中所有程序和 Startup.cs 代码都合并到 Program.cs 中。在问题的情况下,自定义中间件将添加在控制器和 Razor 页面中间件之前。
...
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Write Custom ASP.NET Core Middleware讲解如何编写中间件和调用中间件
Panagiotis 让我找到解决方案,
我必须在端点之前调用中间件,并且调用被触发。
谢谢大家
我有一个使用 .NET Core 2.2 中间件的后端解决方案,我将其更新为 .NET Core 5,但不再触发 InvokeAsync
方法。
这是我的代码:
启动(在配置服务中):
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
有效路由中间件:
public class ValidRouteMiddleware
{
private readonly ILogger<ValidRouteMiddleware> _logger;
private const string BadRouteErrorMessage = "Hello World d~.~b";
private readonly RequestDelegate _next;
private readonly List<string> _allRoutes;
public ValidRouteMiddleware(RequestDelegate next, ILogger<ValidRouteMiddleware> logger,
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_next = next;
_logger = logger;
....
}
public async Task InvokeAsync(HttpContext context)
{
if (!MiddlewareTools.CheckRoute(context,_allRoutes))
{
_...
return;
}
else
{
await _next.Invoke(context);
}
}
}
CheckIdChantierDefaultMiddleware:
public class CheckIdChantierDefaultMiddleware
{
private readonly ILogger<CheckIdChantierDefaultMiddleware> _logger;
private const string UnauthorizedErrorMessage = "Non autorisé";
private readonly RequestDelegate _next;
private readonly List<string> _excludedRoutes;
public CheckIdChantierDefaultMiddleware(RequestDelegate next, ILogger<CheckIdChantierDefaultMiddleware> logger,
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_next = next;
...
}
public async Task InvokeAsync(HttpContext context, ComInDbContext dbContext)
{
}
}
等...
缺少什么?
此致
注:整个Startup/ConfigureServices
public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime, IWebHostEnvironment env, ILogger<Startup> logger)
{
Logger = logger;
Logger.LogInformation($"Environnement d'exécution : {Environment.EnvironmentName}");
appLifetime.ApplicationStarted.Register(OnApplicationStarted);
appLifetime.ApplicationStopping.Register(OnApplicationStopping);
appLifetime.ApplicationStopped.Register(OnApplicationStopped);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
// Pour la génération des PDFs, on doit injecter la lib en 32 ou 64
var wkHtmlToPdfContext = new CustomAssemblyLoadContext();
var architectureFolder = (IntPtr.Size == 8) ? "64 bits" : "32 bits";
// Folder dans Infrastructure.PDF
var wkHtmlToPdfPath = Path.Combine(AppContext.BaseDirectory, $"libwkhtmltox\{architectureFolder}\libwkhtmltox");
wkHtmlToPdfContext.LoadUnmanagedLibrary(wkHtmlToPdfPath);
app.UseRouting();
// Utilisation de la règle du CORS
Logger.LogInformation($"Application de la règle `{filteredOrigin}` pour le CORS");
app.UseCors(filteredOrigin);
// Swagger uniquement en DEV
if (Environment.EnvironmentName == "Development" || Environment.EnvironmentName == "PreProduction")
{
// Active Swagger
Logger.LogInformation($"Activation de Swagger (sur l'URL \"/swagger\") ...");
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Swagger - Administration API");
c.RoutePrefix = String.Empty;
});
}
// Active les signaux de HealthCheck sur l'url de routage "/health"
Logger.LogInformation($"Activation des HealthCheck (sur l'URL \"/health\") ...");
// Active le pipeline d'Endpoints
Logger.LogInformation($"Activation du pipeline d'Endpoints ...");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHealthChecks("/health",
new HealthCheckOptions
{
ResponseWriter = async (context, report) =>
{
var result = JsonSerializer.Serialize(
new
{
status = report.Status.ToString(),
errors = report.Entries.Select(e => new { key = e.Key, value = Enum.GetName(typeof(HealthStatus), e.Value.Status) })
});
context.Response.ContentType = MediaTypeNames.Application.Json;
await context.Response.WriteAsync(result, context.RequestAborted);
}
});
});
app.UseHttpsRedirection();
#region Middleware
// Active le middleware pour la vérification des headers
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
#endregion Middleware
}
我在这里写了一个简单的demo。首先我在startup
中的Configure
方法中创建了一个自定义中间件并在endpoint
之前注册了它,然后你可以看到InvokeAsync触发成功
当我在 endpoint
之后注册中间件时,InvokeAsync 不会被触发。
Panagiotis Kanavos 已经解释了 Endpoint
或者您可以阅读 this 关于路由 Asp .net core 5
我怀疑这段代码是否在 .NET Core 2 中有效。中间件按照请求的注册顺序阻止处理请求。 ASP.NET Core 中的所有内容都是一个中间件块,包括 HTTPS、身份验证、CORS、控制器支持、路由、端点,端点充当中间件链中的 last 步骤。
永远不会调用端点之后注册的任何内容。这包括自定义中间件 和 HTTPS 重定向步骤。
ASP.NET Core middleware page in the docs explains how middleware works and the correct middleware order
至少你需要在 if (env.IsDevelopment())
块之后放置 UseHttpsRedirection
,并在 UseEndpoints
.
我建议创建一个新的 ASP.NET 核心 MVC 应用程序并检查代码。中间件的顺序已经正确。
.NET Core LTS 版本
您还应该考虑跳过 .NET 5 并直接进入 .NET 6。.NET 5 是一个短期版本,达到 End-Of-Life in May 2022。 Long-Term-Support 版本为 .NET 6,将支持到 2024 年 11 月。
从 .NET 5 迁移到 .NET 6 可能就像将目标从 net6.0
更改为 net5.0
并升级 NuGet 包一样简单。另一方面,从新的最小 MVC 模板开始可以显着减少启动代码,从而减少出现此类错误的机会。
再次尝试创建一个新的空 MVC 网络应用程序并检查生成的代码。
middleware doc page 显示了一个 .NET 6 示例,其中所有程序和 Startup.cs 代码都合并到 Program.cs 中。在问题的情况下,自定义中间件将添加在控制器和 Razor 页面中间件之前。
...
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.UseMiddleware<ValidRouteMiddleware>();
app.UseMiddleware<ValidNuisAlgoTokenAndAdminMiddleware>();
app.UseMiddleware<CheckIdChantierDefaultMiddleware>();
app.UseMiddleware<ValidationCatcherMiddleware>();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Write Custom ASP.NET Core Middleware讲解如何编写中间件和调用中间件
Panagiotis 让我找到解决方案, 我必须在端点之前调用中间件,并且调用被触发。
谢谢大家