I created a base controller class called BaseController in my ASP.NET Core 6 project which includes some basic functionality which I need in my other controllers. I also run some additional code in the OnActionExecutionAsync method inside the BaseController which I would otherwise have to run in every single controller action. However, in some rare cases I do not want to run this code before an action. One example for this are any authentication/login related actions. Is there a way how I can skip running the additional code via OnActionExecutionAsync for specific controller actions? I am thinking of something similar to how I can use [AllowAnonymous] to allow access to specific actions for non-authenticated users.
Add a comment
|
1 Answer
Not sure how do you design your BaseController, but usually we custom Action Filters if you want do anything before the action executes.
First way you can custom ActionFilterAttribute and add this attribute on the action which you want to run any other additional code.
public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var controllerName = context.RouteData.Values["controller"].ToString();
string action = context.RouteData.Values["action"].ToString();
//xxxxxxx.Query["YourQueryStringName"].....
var query = context.HttpContext.Request.Query["tenantID"].ToString();
//do your stuff....
}
}
Controller:
public class TestController:BaseController
{
[CustomActionFilter]
public IActionResult Index()
{
return Ok();
}
}
Second way you can get your request controller and action name in the method to make them as a condition:
public class CustomActionFilter: IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
var controllerName = context.RouteData.Values["controller"].ToString();
string action = context.RouteData.Values["action"].ToString();
if(controllerName!="xxx"&&action!="xxx")
{
//do your stuff...
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
Note:
If you want to get the controller and action value, be sure you configure the route template like below:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
6 Comments
Chris
Thanks! The reason why I implemented
OnActionExecutionAsync in the BaseController and not in a filter is that I need to write to a few fields/properties which I then use in the child controllers. I couldn't find an easy way to do the same thing in a custom filter (at least not without doing something hacky). I like your first solution but I see the same problem there. How can I access controller properties in OnActionExecutionAsync with that solution (without using Reflection or doing anything similar)?Rena
Hi @Chris, for the first solution, why do you want to access controller properties? Actually if you set the attribute on action, only this action can invoke the
OnActionExecutionAsync .Chris
My application has to support multitenancy. In order to make this work, I have to read the tenant ID that the frontend provides as a query argument, validate it (check if the user is actually allowed to access this tenant) and then I set it as a property in the
BaseController which I can then use in the controller actions when interacting with the business logic and data access layers. If I don't do it this way, I would have to add this code in every single action (or at least call 1-2 functions that run this code) which would result in a lot of redundant code.Rena
Hi @Chris, ok, I got it. BTW, what is your OnActionExecutionAsync like? Is it similar with what I did in the first solution? Actually I mean do you have
ActionExecutingContext in OnActionExecutionAsync . Also for confirm, you want to get the tenant ID which is query string in url,right?Rena
Hi @Chris, I have updated my answer. Pls check.
|