Search code examples
asp.net-web-apiauthorize-attributeasp.net-web-api2

Get the api controllers constructor value within an AuthorizeFilter


When the user is authenticated I want to prevent that he updates/deletes/reads data created from other accounts... by telling him you do not have the permission 403!

What is the best way to get an instance of the ISchoolyearService to invoke its HasUserPermission() method?

I know I could new up the SchoolyearService here but that would defeat the reason using an IoContainer at all in my app.

public class UserActionsSchoolyearAuthorizationFilter : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (actionContext != null)
        {
            bool canUserExecuteAction = false;
            if (actionContext.Request.Method == HttpMethod.Put)
            {
                int schoolyearId = Convert.ToInt32(actionContext.Request.GetRouteData().Values["Id"]);
                int userId = actionContext.Request.Content.ReadAsAsync<SchoolyearEditRequest>().Result.Schoolyear.UserId;
                //var schoolyearService = actionContext.ControllerContext.Controller.GetContstructorParameterServiceInstance();
                //canUserExecuteAction = schoolyearService.HasUserPermission(userId, schoolyearId);
                if (canUserExecuteAction)
                {
                    base.OnAuthorization(actionContext);
                }
                else
                {
                    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
                }

            }
            // Removed for brevity

    private readonly ISchoolyearService _service;
            public SchoolyearController(ISchoolyearService service)
            {
                _service = service;
            }

Solution

  • Ok finally I found it out how to get the ISchoolyearService from the current request:

    Grab the registered service from the DependencyScope!

    Now this Attribute should be put on the controller directly. Its not needed to put it on the action due to the if/else on the http verbs which I do.

    bool canUserExecuteAction = false;
    if (actionContext.Request.Method == HttpMethod.Put)
    {
        int targetId = Convert.ToInt32(actionContext.Request.GetRouteData().Values["Id"]);
        int userId = actionContext.Request.Content.ReadAsAsync<SchoolyearEditRequest>().Result.Schoolyear.UserId;
        var requstScope = actionContext.ControllerContext.Request.GetDependencyScope();
        var service = requstScope.GetService(typeof(ISchoolyearService)) as ISchoolyearService;
        canUserExecuteAction = service.HasUserPermission(userId, targetId);
    
        if (canUserExecuteAction)
        {
            base.OnAuthorization(actionContext); 
        }
        else
        {
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
        }
    }