Home > Software design >  How do I get the controller endpoint information in an attribute?
How do I get the controller endpoint information in an attribute?

Time:03-23

I have an ASP.NET Web API with a bunch of controllers and actions. By using EndpointDataSource I can get a list of all endpoints in the API, which is used during startup to maintain a Controllers and an Actions table. I am going to link these records to a Roles table so I can manage roles to specific actions and controllers without changing the code. This would allow the admin to create custom roles that provide access to these controllers and actions. The API already has a custom authentication mechanism where users are assigned to various roles so I cannot use "standard" solutions for role management. (The login process is a bit complex.)
So I want to create a class attribute [ClassRole] and a method attribute [ActionRole] to attach to any action that needs to be managed through roles. So I have this code: [AttributeUsage(AttributeTargets.Class)]

public class ControllerRoleAttribute : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
    }
}
[AttributeUsage(AttributeTargets.Method)]
public class ActionRoleAttribute : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
    }
}

And these methods need to do something. Basically, the lookup in the database for the controller name or action name is easy. But how do I get the controller name and action name from this AuthorizationFilterContext class? Preferably without having to parse an URL or whatever.
FYI: The ActionRoleAttribute will first validate the role by the controller before validating by action.
In both cases, when the validation fails, a custom exception will be raised and additional data gets logged. This is also why I need a separate solution. Also, if the current user has the Admin or SuperAdmin status, the roles will not be checked but access is granted automatically.
This API had quite a few controllers with just a few actions each. Each controller is a logical unit that handles related actions. Most of these actions deal with data management and tend to be sensitive information. It's a bit complex as user management itself is also a bit complex as users are divided into groups and subgroups and roles can be assigned to a specific user, a group or a subgroup. Admins only control their own groups and subgroups while the SuperAdmin would be me. I should be able to do everything.
What matters most of all is getting the controller name!

CodePudding user response:

The AuthorizationFilterContext class has a property called ActionDescriptor that holds the detail you require. However, it uses a derived class that is specific to controllers, so you need to cast it to a ControllerActionDescriptor get at the relevant details. So you can do something like this:

public void OnAuthorization(AuthorizationFilterContext context)
{
    if (context.ActionDescriptor is 
            ControllerActionDescriptor controllerActionDescriptor)
    {
        var actionName = controllerActionDescriptor.ActionName;
        var controllerName = controllerActionDescriptor.ControllerName;
    }
}
  • Related