将ActionFilter.OnActionExecuting()中的对象传递给ApiController

时间:2015-02-06 01:28:57

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

我希望在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的实例传递给控制器​​,因为在调用控制器方法时,新的属性[" CustomObjectKey"]在Webapi管道中丢失。

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

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

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

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

Edit-1:此问题v1中提到的MyAuthorizationFilter实际上是一个身份验证过滤器。还在调查。

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

2 个答案:

答案 0 :(得分:17)

您必须使用.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;
}

答案 1 :(得分:0)

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

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

注意使用ActionFilterAttribute Web API:

  

System.Web.Http.Filters.ActionFilterAttribute

MVC classic:

  

System.Web.Mvc.ActionFilterAttribute

使用:

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