ASP.NET Core MVC 2.0中间件获取UrlHelper:ActionContext返回null
解决ASP.NET Core MVC 2.0中间件中ActionContextAccessor.ActionContext为null的问题
我来帮你搞定这个问题!你遇到的actionContextAccessor.ActionContext始终返回null的情况,大概率是中间件注册顺序不对,或者你在错误的时机去获取它了,下面给你详细分析和解决方案:
问题根源
在ASP.NET Core的请求管道里,ActionContext是由MVC中间件(也就是app.UseMvc())在处理请求的过程中,才会把当前请求的上下文设置到ActionContextAccessor中的。如果你的自定义中间件注册在app.UseMvc()之前,那当中间件执行时,MVC还没来得及初始化ActionContext,自然就拿不到有效值。
解决方案
1. 调整中间件注册顺序(最常用的解决方式)
把你的自定义中间件放在app.UseMvc()之后注册,确保请求流经你的中间件时,MVC已经完成了ActionContext的初始化。示例Configure方法代码如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseSession(); app.UseAuthentication(); // 先注册MVC中间件,让它完成ActionContext的初始化 app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); // 再注册你的自定义中间件 app.UseMiddleware<YourCustomMiddleware>(); }
2. 手动构建ActionContext(特殊场景下使用)
如果你因为业务需求,必须在MVC中间件之前使用UrlHelper,那可以手动通过HttpContext构建ActionContext,再赋值给ActionContextAccessor。示例中间件代码:
public class YourCustomMiddleware { private readonly RequestDelegate _next; private readonly IUrlHelperFactory _urlHelperFactory; private readonly IActionContextAccessor _actionContextAccessor; public YourCustomMiddleware(RequestDelegate next, IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor) { _next = next; _urlHelperFactory = urlHelperFactory; _actionContextAccessor = actionContextAccessor; } public async Task Invoke(HttpContext context) { // 检查ActionContext是否为null,为空则手动创建 if (_actionContextAccessor.ActionContext == null) { var routeData = context.GetRouteData(); var actionDescriptor = new ActionDescriptor(); var actionContext = new ActionContext(context, routeData, actionDescriptor); _actionContextAccessor.ActionContext = actionContext; } // 现在可以正常创建UrlHelper并使用了 var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext); var exampleUrl = urlHelper.Action("About", "Home"); // 执行后续中间件 await _next(context); } }
3. 确认ConfigureServices配置的正确性
你当前的ConfigureServices里手动注册IActionContextAccessor是正确的——ASP.NET Core 2.0中AddMvc()并没有默认注册这个服务,所以services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()这一步不能少,你的配置这部分没问题。
内容的提问来源于stack exchange,提问作者KevinBui
相关产品推荐
相关产品推荐

