【问题标题】:Why is my ASP.NET Web API ActionFilterAttribute OnActionExecuting not firing?为什么我的 ASP.NET Web API ActionFilterAttribute OnActionExecuting 没有触发?
【发布时间】:2012-10-11 03:48:10
【问题描述】:

我正在尝试实现这里看到的内容:http://www.piotrwalat.net/nhibernate-session-management-in-asp-net-web-api/,但我的NhSessionManagementAttribute 有问题。

我在OnActionExecuting(HttpActionContext actionContext) 上设置了断点,以查看该函数是否被调用过——实际上没有。

我仔细检查了我的global.asax.cs 文件,发现我实际上正在注册ActionFilter:

GlobalConfiguration.Configuration.Filters.Add(new NhSessionManagementAttribute());

我还用属性修饰了我的控制器类本身,以及它的操作,但无济于事:

public class ClientsController : ApiController {
    static readonly ClientRepository repository = new ClientRepository();

    [NhSessionManagement]
    public IEnumerable<Client> GetAllClients() {
        return repository.GetAll();
    }

    [NhSessionManagement]
    public Client GetClient(int id) {
        Client client = repository.Get(id);
        if (client == null) {
            throw new HttpResponseException(
                new HttpResponseMessage(HttpStatusCode.NotFound)
            );
        }
        return client;
    }
}

为什么这个动作过滤器不会触发其中的任何事件?

【问题讨论】:

    标签: c# asp.net-web-api action-filter actionfilterattribute


    【解决方案1】:

    如果您在一个同时包含 MVC 和 WebAPI 程序集的项目中工作,您能否检查一下您的 ActionFilterAttribute 的命名空间是什么命名空间。这相当令人困惑,因为两者下都有两个 ActionFilterAttributes:

    • WebAPI:System.Web.Http.Filters
    • MVC:System.Web.Http.Mvc

    【讨论】:

    • 对于 WebAPI,应该使用 System.Web.Http.Mvc 过滤属性,对吗?
    • 我一直在试图弄清楚为什么我的 ActionFilter 在过去几个小时内无法正常工作。谢谢特洛伊! :)
    • WebApi 的 ActionFilterAttribute 位于 System.Web.Http.dll 程序集中。
    • MVC: System.Web.Http.Mvc --> System.Web.Mvc 在某些 ASP.NET MVC 版本中
    • 我还是一头雾水。对于 WebAPI,为什么 System.Web.Http.Filters.ActionFilterAttribute 不是合适的选择?答案只是说检查命名空间并声明有两个。它没有解释你为什么不使用 WebAPI。
    【解决方案2】:

    上面的答案肯定对我有所帮助 - 为其他人节省一些时间......这就是明显的区别。

    标准 MVC 控制器使用:

    // System.Web.Mvc
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }
    

    OData HTTP 控制器使用:

    // System.Web.Http.Filters;
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);
    }
    

    【讨论】:

    • System.Web.Http.Filters 也适用于 WebApi。如果使用 Ninject,请务必注意过滤器绑定在 Mvc 和 Http 的不同库中。 Mvc - Ninject.Web.Mvc WebApi/Http - Ninject.Web.WebApi
    • 实际上,HTTP Controller 使用应该显示 OnActionExecuting(HttpActionContext httpActionContext) 然后调用 base.OnActionExecuting(httpActionContext)。 OnActionExecuted() 也可用。
    【解决方案3】:

    对于遇到此问题的任何其他人,从 UnitTest 调用 YourController.YourAction 时,ActionFilterAttribute 不会触发。

    [TestMethod]
    public void RevokeSiteAdmin_SessionOver()
    {
        FakeDbContext db = new FakeDbContext();
    
        YourController controller = new YourController(db);
        var result = controller.YourAction();
    
        //Some Assertions
    }
    

    在上面的 TestMethod 中,不会调用 YourController.YourAction 上的任何 ActionFilterAttributes。然而;如果你从浏览器调用 YourController.YourAction,你的 ActionFilterAttribute 将会被调用。

    至少对于 WebApi 是这样,但我不知道它是否适用于 MVC。

    【讨论】:

      【解决方案4】:

      这是完整的实现:

      public class AllowCrossSiteJsonAttribute : System.Web.Mvc.ActionFilterAttribute
      {
          public override void OnActionExecuted(System.Web.Mvc.ActionExecutedContext filterContext)
          {
              if (filterContext.HttpContext != null && filterContext.HttpContext.Response != null && filterContext.HttpContext.Request != null && filterContext.HttpContext.Request.UrlReferrer != null)
              {
                  var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
                  var allowedHosts = allowedCrossDomains.Split(',');
      
                  var requestHost =  filterContext.HttpContext.Request.UrlReferrer.GetLeftPart(UriPartial.Authority);
                  if (allowedHosts.Contains(requestHost.ToLower()))
                  {
                      filterContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
                  }
              }
      
              base.OnActionExecuted(filterContext);
          }
      }
      public class AllowCrossSiteJsonForWebApiAttribute : ActionFilterAttribute
      {
          public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
          {
              if (actionExecutedContext.Response != null && actionExecutedContext.Request != null &&
                  actionExecutedContext.Request.Headers.Referrer != null)
              {
                  var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
                  var allowedHosts = allowedCrossDomains.Split(',').ToList();
      
                  var requestHost = actionExecutedContext.Request.Headers.Referrer.GetLeftPart(UriPartial.Authority);
      
                  if (allowedHosts.Contains(requestHost.ToLower()))
                  {
                      actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
                  }
      
                  base.OnActionExecuted(actionExecutedContext);
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        对于 WebApi,您应该从 nuget 安装 Microsoft.AspNet.WebApi.Core。 对于 MVC,您可以使用 System.Web.MVC。

        【讨论】:

          【解决方案6】:

          我的问题要简单得多:

          检查您的控制器是否用&lt;actionPreProcessActivitiesAttribute()&gt; _ 装饰

          【讨论】:

            猜你喜欢
            • 2015-09-13
            • 1970-01-01
            • 2017-10-14
            • 2014-07-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多