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
    }
}
m3rt_ali
  • 73
  • 1
  • 9

2 Answers2

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)
d_f
  • 4,599
  • 2
  • 23
  • 34
  • Yes, that is exactly what i want. But not sure why they had changed the life cycle in .NetCore. Thanx anyway :) – m3rt_ali Jun 13 '18 at 13:52
  • 1
    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 : ) – d_f Jun 13 '18 at 15:38
  • i would love to but not enough reputations :( – m3rt_ali Jun 13 '18 at 16:17
  • @d_f 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? – remcolam Oct 07 '19 at 16:58
  • @remcolam 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 services – d_f Oct 07 '19 at 17:23
  • Yeah, I noticed (by setting breakpoints) that the controller constructor isn't called yet at onauthorize. – remcolam Oct 08 '19 at 18:12
  • 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 format – remcolam Oct 08 '19 at 18:18
3

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.

Tangere Apps
  • 216
  • 4
  • 5