【问题标题】:Access Controller from ExceptionFilterAttribute in ASP.NET Core来自 ASP.NET Core 中 ExceptionFilterAttribute 的访问控制器
【发布时间】:2018-08-09 05:48:51
【问题描述】:

使用 ASP.Net Core 2,如何访问应用了 ExceptionFilterAttribute 的 Controller 实例?

现在在 Core 中是否有更好的方法来实现共享的“基本”控制器属性和方法等?比如放到Startup之类的更高层次?

在 Core 之前,在 MVC 4 中,我会做这样的事情:

/// <summary>
/// Base controller, shared by all WebAPI controllers for tracking and shared properties.
/// </summary>
[ApiTracking]
[ApiException]
public class BaseApiController : ApiController
{
    private Common.Models.Tracking _Tracking = null;
    public Common.Models.Tracking Tracking
    {
        get
        {
           if(_Tracking == null)
               _Tracking = new Common.Models.Tracking();
           return _Tracking;
        }
    }
    //... other shared properties...
}

/// <summary>
/// Error handler for webapi calls. Adds tracking to base controller.
/// </summary>
public class ApiExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext cntxt)
    {
        BaseApiController ctrl = cntxt.ActionContext.ControllerContext.Controller as BaseApiController;
        if (ctrl != null)
            ctrl.Tracking.Exception(cntxt.Exception, true);

        base.OnException(actionExecutedContext);
    }
}

/// <summary>
/// Intercepts all requests to inject tracking detail and call tracking.save.
/// </summary>
public class ApiTrackingAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext cntxt)
    {
        //...add info to tracking
    }
    public override void OnActionExecuted(HttpActionExecutedContext cntxt)
    {
        BaseApiController ctrl = cntxt.ActionContext.ControllerContext.Controller as BaseApiController;
        if (ctrl != null)
            ctrl.Tracking.Save();
    }
}

【问题讨论】:

标签: c# asp.net-core


【解决方案1】:

ASP.Net Core 中的HttpContext 包含IDictionary&lt;object, object&gt; 类型的Items 属性,用于在请求范围内共享数据。这正是您处理案件所需要的。这是一个示例实现:

public class ApiExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        var items = context.HttpContext.Items;
        if (items.ContainsKey("Tracking"))
        {
            Tracking tracking = (Tracking)items["Tracking"];
            tracking.Exception(context.Exception, true);
        }

        base.OnException(context);
    }
}

public class ApiTrackingAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var tracking = new Tracking();
        //...add info to tracking

        context.HttpContext.Items.Add("Tracking", tracking);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var items = context.HttpContext.Items;
        if (items.ContainsKey("Tracking"))
        {
            Tracking tracking = (Tracking) items["Tracking"];
            tracking.Save();
        }
    }
}

【讨论】:

  • 使用HttpContext.Items获取属性很好,但我正在寻找控制器上下文,我们如何从ExceptionContext找到ControllerContext
  • 之前ActionContext 中有ControllerContext 属性,ExceptionContext 继承自该属性。但它已被删除,详情请查看this issue on GitHub。我的回答涵盖了原始问题,OP 不需要ControllerContext 来实现他的目标。
  • 感谢@CodeFuller。我会尽快对此进行测试。我总是使用基本控制器的原因之一是,在派生控制器中,我也会将 this.Tracking 传递给助手调用等,因此跟踪主要由助手填充。使用 context.items 应该可以解决问题。
  • @CodeFuller 这确实解决了我在过滤器中访问内容的问题。我还在为过滤器无序执行的事实而苦苦挣扎……所以在我的情况下,跟踪是在捕获异常之前保存的。我会在这个话题之外解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 2023-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
相关资源
最近更新 更多