Get Controller instance in AuthorizeAttribute Mvc Core Web Api
Asked Answered
E

2

4

I had used below class to to control my api method request and setup some properties of BaseController class to use in methods commonly. this one is from Asp.Net Mvc Web Api

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class AuthUserAttribute : AuthorizeAttribute
{

    private string Action { get; set; }

    public AuthUserAttribute(string action)
    {
        this.Action = action;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        BaseController baseController = httpContext.ControllerContext.Controller as BaseController;
        baseController.someCommenProperty = someValue;
    }
}

But when i am trying to implement same struct in Asp.Net Mvc Core Api I could not reached instance of controller that initialized. Is there any way i can get that instance.

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using System;
using System.Linq;

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class AuthUserAttribute : AuthorizeAttribute, IAuthorizationFilter
{


    private string Action { get; set; }
    public AuthUserAttribute(string action)
    {
        this.Action = action;
    }



    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // how to get controller instance from context
    }
}
Euhemerus answered 7/6, 2018 at 17:31 Comment(0)
C
7

You may use context.ActionDescriptor to get the Type information on the controller.
The controller object might be not instantiated at all at the moment of authorization check.
You may additionally implement IActionFilter and use the controller instance in it's

public void OnActionExecuting(ActionExecutingContext context)

and

public void OnActionExecuted(ActionExecutingContext context)
Croom answered 9/6, 2018 at 18:9 Comment(7)
Yes, that is exactly what i want. But not sure why they had changed the life cycle in .NetCore. Thanx anyway :)Euhemerus
As I see it, today they think more about global consistency than about backward compatibility and legacy code -- it just has to be rewritten : ) Anyway if an answer is useful, or (maybe) it's the really answer, don't hesitate to vote or mark, today and later on : )Croom
i would love to but not enough reputations :(Euhemerus
@Croom I need information from the controller instance to know if authorization succeeds. The controller is configured in a certain way. How do you suggest I get the information out of the controller during authorization? Should I just create a new instance?Comical
@Comical your question is not clear enough, at least for me. As I answered above, the controller might be not instantiated during the IAuthorizationFilter is doing its work. when you need a controller object, in an attribute, that must be an IActionFilter. when these two options does not fit as you need some info from the controller internals to make your auth decision, then you have some problems with the logic -- it'd better to move such stuff outside, to the servicesCroom
Yeah, I noticed (by setting breakpoints) that the controller constructor isn't called yet at onauthorize.Comical
But how using an actionfilter, how do you return unauthorized correctly there? We want to set a collection of data based on the authorize results in the controller. But now that I think of this, this is bypassing the whole authorize flow, maybe I should create a mvc user, with my own custom claims. In the onaction executing I can then retrieve the data from that and expose the claims in a more easy formatComical
F
4

For anyone looking for a solution today using .NET 6, you can access the controller instance in a type filter by implementing both Microsoft.AspNetCore.Mvc.Filters.IActionFilter and the filter type interface (e.g., Microsoft.AspNetCore.Mvc.Filters.IExceptionFilter). Consider the following as a working example.

[TypeFilter(typeof(ExceptionFilter))]
public class MyController : ControllerBase
{

}

public class ExceptionFilter : IExceptionFilter, IActionFilter
{
    private MyController? MyController { get; set; }

    public void OnActionExecuted(ActionExecutedContext context)
    {
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        this.MyController = (MyController)context.Controller;
    }

    public void OnException(ExceptionContext context)
    {
        // Do something using this.MyController
    }
}

Note: OnActionExecuting occurs before OnException.

Floc answered 14/6, 2022 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.