【问题标题】:Pass an object from ActionFilter.OnActionExecuting() to an ApiController将一个对象从 ActionFilter.OnActionExecuting() 传递给 ApiController
【发布时间】:2015-02-06 01:28:57
【问题描述】:

我希望在 ActionFilter 中为每个 http 请求创建一个对象,并将该对象传递给控制器​​。到目前为止,我已经尝试过如下所示的 Request.Properties[]

public class DbReadonlyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        actionContext.Request.Properties["CustomObjectKey"] = new MyClass();

我还尝试将新对象直接分配给 ControllerBase 类。

public class DbReadonlyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var controller = (MyControllerBase) actionContext.ControllerContext.Controller;
        controller.StorageContextFactory = new MyClass();

问题在于这两种技术都没有将 MyClass 的实例传递给控制器​​,因为在调用控制器方法时,新的 Property["CustomObjectKey"] 在 Webapi 管道中丢失了。

控制器在调用操作过滤器 OnActionExecuting() 之后由 webapi 管道重新实例化。

断点确认 Webapi 管道在单个 http 请求期间安排以下事件流。

  • 构造函数 MyControllerBase()
  • MyAuthenticationFilter
  • 过滤 OnActionExecuting()
  • 构造函数 MyControllerBase()
  • MyController.MethodA()

MyControler 的双重实例化很奇怪,但现在我正在寻找将新创建的对象从动作过滤器传递到控制器的任何技术。

Edit-1:这个问题 v1 中提到的 MyAuthorizationFilter 实际上是一个 Authentication 过滤器。仍在调查中。

解决方案:错误在另一个过滤器中。删除身份验证过滤器后,此问题中报告的问题就消失了。

【问题讨论】:

    标签: asp.net-web-api action-filter


    【解决方案1】:

    您将不得不使用.add 方法Request.Properties 集合。

    public class DbReadonlyAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            actionContext.Request.Properties.Add(new KeyValuePair<string, object>("CustomObjectKey", new MyClass()));
    

    您可以从您的 api 控制器中检索此值。

    object _customObject= null;
    
    if (Request.Properties.TryGetValue("CustomObjectKey", out _customObjectKey))
    {
        MyClass myObject = (MyClass)_customObject;
    }
    

    【讨论】:

    • 感谢您的意见,在应用您的代码更改后我仍然遇到问题,我现在怀疑我的身份验证过滤器中的异步链接存在更深层次的问题。
    • 我一直在使用我在答案中粘贴的代码。它对我来说很好。
    • 我通过删除在 WebApiConfig 中声明为 config.Filters.Add(x); 的全局身份验证过滤器来简化问题。使用您的示例和我的原始 Properties["CustomObjectKey"] = 技术从我的操作过滤器传递到控制器的对象适用于这两个示例。我现在正在调查为什么我的身份验证过滤器会导致问题,例如双控制器实例化。如果我解决了这个问题,我会回来并相信你的回答,因为你的建议让我寻找更深层次的问题。
    • 将此标记为正确答案,因为确认可以通过请求属性将对象引用从动作过滤器传递到控制器,这迫使我查看导致解决方案的整个过滤器链。
    【解决方案2】:

    另一种将变量从 ActionFilter.OnActionExecuting() 传递到 ApiController 的方法:

    public class CustomFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext actionContext)
        {
            actionContext.ControllerContext.RequestContext.RouteData.Values["CustomValue"] = "CustomValue";
        }
    }
    

    注意Web API 使用 ActionFilterAttribute :

    System.Web.Http.Filters.ActionFilterAttribute

    不适用于 MVC 经典:

    System.Web.Mvc.ActionFilterAttribute

    使用:

    [CustomFilter]
    public class SomeController : ApiController
    {
        string customValue = RequestContext.RouteData.Values.ToDictionary(x => x.Key, y => y.Value)["user_id"].ToString();
        //...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      相关资源
      最近更新 更多