Search code examples
asp.net-web-apiaction-filter

Pass an object from ActionFilter.OnActionExecuting() to an ApiController


I wish to create an object per http request within an ActionFilter and pass this object to the controller. So far I have tried Request.Properties[] like the following

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

And I have also tried to assign the new object direct to a ControllerBase class.

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

The problem is that neither technique delivers an instance of MyClass to the controller because the new Property["CustomObjectKey"] is lost in the Webapi pipeline by the time a controller method is invoked.

The controller is re-instantiated by the webapi pipeline after the call to action filter OnActionExecuting().

Break points confirm the Webapi pipeline schedules the following event flow during a single http request.

  • constructor MyControllerBase()
  • MyAuthenticationFilter
  • Filter OnActionExecuting()
  • constructor MyControllerBase()
  • MyController.MethodA()

The double instantiation of MyControler is odd, but right now I am looking for any technique to pass a newly created object from an action filter to a controller.

Edit-1: The MyAuthorizationFilter mentioned in v1 of this question is actually an Authentication filter. Still investigating.

Solution: The bug was in another filter. After I removed my authentication filter the problem reported in this question went away.


Solution

  • You will have to use .add method Request.Properties collection.

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

    You can retrieve this value from your api controller.

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