Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 610
camelCase Avatar asked Feb 06 '15 01:02

camelCase


People also ask

Can we pass object as a parameter to Web API GET method?

It clearly states Can't bind multiple parameters. This indicates that we cannot pass multiple entities as an input parameter to Web API action methods.

What is the use of ApiController?

The [ApiController] attribute applies inference rules for the default data sources of action parameters. These rules save you from having to identify binding sources manually by applying attributes to the action parameters.

How do I use action filter in Web API?

Action filters contain logic that is executed before and after a controller action executes. You can use an action filter, for instance, to modify the view data that a controller action returns. Result filters contain logic that is executed before and after a view result is executed.

How do I return a view from Web API action?

So, if you want to return a View you need to use the simple ol' Controller . The WebApi "way" is like a webservice where you exchange data with another service (returning JSON or XML to that service, not a View). So whenever you want to return a webpage ( View ) for a user you don't use the Web API.


1 Answers

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;
}
like image 160
Sameer Azazi Avatar answered Nov 02 '22 20:11

Sameer Azazi