ASP.NET Core中IWebHostBuilder.Configure()为何未执行?(3.4.0版本)
嘿,这个问题我之前折腾过好一会儿!核心原因很简单:当你在ConfigureWebHostDefaults里先调用Configure()再调用UseStartup<Startup>()时,UseStartup会直接覆盖掉你之前通过Configure()注册的应用管道配置委托。在ASP.NET Core 3.x及以后的版本里,UseStartup<T>的优先级更高,它会把Startup类的Configure方法设为管道配置的主要入口,导致你之前写的UseSerilogRequestLogging完全不会被执行。
为啥会这样?
ASP.NET Core的Web主机构建逻辑里,IWebHostBuilder.Configure()是用来直接注册管道配置代码的,但一旦你调用了UseStartup<T>,框架内部会替换掉之前的配置委托,转而使用Startup类里的Configure方法来搭建整个请求管道。相当于你前面写的Configure代码被“覆盖清零”了,自然不会生效。
解决办法,分三种场景选
场景1:想彻底集中配置,不用Startup类
如果你本来就想把所有配置集中在一处,完全可以抛弃Startup类,直接用webBuilder的ConfigureServices和Configure来搞定所有事情:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder .UseSerilog(...) // 原来Startup.ConfigureServices里的服务注册都放这儿 .ConfigureServices(services => { services.AddControllersWithViews(); // 比如注册DbContext、Auth服务等等 }) // 管道配置直接写在这儿,Serilog请求日志自然排在最前面 .Configure(appBuilder => { appBuilder.UseSerilogRequestLogging(...); // 原来Startup.Configure里的中间件按顺序加 appBuilder.UseHttpsRedirection(); appBuilder.UseStaticFiles(); appBuilder.UseRouting(); appBuilder.UseAuthorization(); appBuilder.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }); });
这种方式最直接,完全符合你“集中管理日志配置”的需求,而且能保证Serilog中间件在管道最开头。
场景2:想保留Startup类,同时在它之前加中间件
如果你不想放弃Startup类,那可以用IStartupFilter来实现“在Startup.Configure执行前插入中间件”的效果——这也是ASP.NET Core官方推荐的扩展管道的方式。
第一步:写个StartupFilter类
public class SerilogRequestLoggingFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return app => { // 先加Serilog请求日志,保证在最前面 app.UseSerilogRequestLogging(...); // 再执行原来的Startup.Configure逻辑 next(app); }; } }
第二步:注册这个Filter
不管你是在webBuilder.ConfigureServices里,还是在Startup类的ConfigureServices里,加这么一行:
services.AddTransient<IStartupFilter, SerilogRequestLoggingFilter>();
这样一来,不管Startup里的Configure怎么写,Serilog的中间件都会自动排在管道最前面,而且日志相关的配置都集中在这个Filter里,不用散在Startup中。
场景3:(不推荐)调整调用顺序
如果你非要用Configure()+UseStartup()的组合,那得把Configure()放在UseStartup()后面。但这样的话,Startup.Configure里的中间件会排在前面,你加的Serilog日志会被放到管道后面,完全不符合你“放在开头”的需求,所以这个方案只提一下,不推荐用。
内容的提问来源于stack exchange,提问作者Leaky

