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

camelCase picture camelCase · Feb 6, 2015 · Viewed 11.9k times · Source

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.

Answer

Sameer Azazi picture Sameer Azazi · Feb 6, 2015

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;
}