You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core如何获取异常来源控制器的ControllerContext实例

实现方案

UseExceptionHandler 触发错误处理逻辑时,会复用原有HttpContext对象重新走一遍请求管道到ErrorController,原始请求执行到异常Controller时生成的ControllerContext不会被默认持久化,需要在MVC执行阶段提前把上下文存下来,异常处理时直接读取即可。


步骤1:添加全局过滤器捕获原始Controller上下文

新增一个Action过滤器,在请求进入任意Controller的Action执行前,把当前的Controller实例/ControllerContext存入HttpContext的Items字典(这个字典在同一次请求的整个生命周期,包括异常重处理阶段都不会丢失):

public class StoreOriginalControllerContextFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // 存储当前Controller实例,后续可直接通过它拿到ControllerContext
        context.HttpContext.Items["__OriginalController"] = context.Controller;
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // 无需处理执行完成逻辑
    }
}

在Startup.ConfigureServices中注册这个全局过滤器,保证所有Action执行前都会触发存储逻辑:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add<StoreOriginalControllerContextFilter>();
        // 其他原有MVC配置
    });
    // 其他服务注册逻辑
}

步骤2:在错误控制器中读取原始上下文

修改ErrorController的Index逻辑,从HttpContext.Items中取出之前存储的原始Controller实例,即可拿到对应的ControllerContext:

public class ErrorController : Controller
{
    public IActionResult Index()
    {
        var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionFeature == null || exceptionFeature.Error == null)
        {
            // 原代码漏了throw关键字,这里已修正
            throw new Exception("Please configure app.UseExceptionHandler(\"/Error/Index\");");
        }

        // 读取原始抛出异常的Controller实例
        if (HttpContext.Items.TryGetValue("__OriginalController", out var storedValue)
            && storedValue is ControllerBase originalController)
        {
            // 这里拿到的就是抛异常的TestController实例,它的ControllerContext就是你要的原始上下文
            ControllerContext originalContext = originalController.ControllerContext;
            
            // 可按需读取原始上下文的路由数据、请求参数、ModelState等信息
            var originalRouteData = originalContext.RouteData;
            var originalModelState = originalContext.ModelState;
        }

        return View();
    }
}

注意事项

  • 该方案仅对进入MVC Controller执行阶段后抛出的异常有效,如果异常发生在MVC中间件之前(比如其他自定义中间件报错、静态文件处理阶段报错、路由匹配失败),不会生成ControllerContext,Items中自然也拿不到对应值,符合正常逻辑。
  • IExceptionHandlerPathFeature仅会记录异常对象、异常发生的请求路径,不会持有MVC执行阶段的上下文对象,无法直接从这个特性里拿到原始ControllerContext。

内容的提问来源于stack exchange,提问作者LHA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:54:08