2

In an ASP.Net Core WebApp I want to use an ActionFilter and send information from the ActionFilter to the controller it is applied to.

MVC

For MVC I can do this

ActionFilter

    public class TenantActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            //Using some sneaky logic to determine current tenant from domain, not important for this example
            int tenantId = 1;
            Controller controller = (Controller)context.Controller;
            controller.ViewData["TenantId"] = tenantId;
        }
        public void OnActionExecuted(ActionExecutedContext context) { }
    }

Controller

    public class TestController : Controller
    {
        [ServiceFilter(typeof(TenantActionFilter))]
        public IActionResult Index()
        {
            int tenantId = ViewData["TenantId"];
            return View(tenantId);
        }
    }

It works and I can pass data back to the controller via ViewData - great.

WebApi

I want to do the same for WebApi Controllers.

The actionFilter itself can be applied, runs etc - but I cannot write to ViewData, because WebAPI inherits from ControllerBase - not from Controller (like MVC).

Question

How can I push data from my ActionFilter back to the calling ControllerBase, similar to MVC?

Notes

  • ASP.Net Core 2.2 being used, but I would be surprised if a solution would not be usable in all of .Net Core.

1 Answer 1

5

...So I found the answer when I was almost done writing the question, so here goes...

The answer is the HttpContext.Items collection

ActionFilter

    public class TenantActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            int tenantId = 1;
            var controller = (ControllerBase)context.Controller;
            controller.HttpContext.Items.Add("TenantId", tenantId);
        }
        public void OnActionExecuted(ActionExecutedContext context) { }
    }

Controller

    public class TestApiController : ControllerBase
    {
        [ServiceFilter(typeof(TenantActionFilter))]
        public SomeClass Get()
        {
            int tenantId;
            if (!int.TryParse(HttpContext.Items["TenantId"].ToString(), out tenantId))
            {
                tenantId = -1;
            }
            return new SomeClass();
        }
    }
Sign up to request clarification or add additional context in comments.

2 Comments

Holding state seems at odds with the notion of a stateless controller.
For a multitenant application, I need to determine which domain the method called is associated with. I could do that directly in the actionmethod, but wrapping it up in a reusable actionfilter seems much cleaner - to me at least.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.