7

I have a controller and action that's responsible for handling 403s due to the users not being in the correct roles. It has access to the original RequestContext that caused the exception.

What I would like to be able to do is decorate my actions with a description of what they do, then allow the user to notify their manager, requesting access including the description in an email.

So, how can I work out what action would be called given a RequestContext?

Obviously this is more complicated that getting controller and action names out of the RouteData since there are often overloads of an action method etc.

Once I have the MethodInfo then it's easy to get attributes etc.

George Duckett
  • 31,770
  • 9
  • 95
  • 162

3 Answers3

11

Here's an extension method for you. If you're doing dependency injection on your controllers (non-parameterless constructor), you'll need to enumerate the controller constructors with reflection, or use your IOC container to instantiate your controller, rather than using Activator.CreateInstance. Also, this can be modified to work with similar context's like ExceptionContext or HttpContext pretty easily.

public static class RequestContextExtensions
{
    public static MethodInfo GetActionMethod(this RequestContext requestContext)
    {
        Type controllerType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == requestContext.RouteData.Values["controller"].ToString());
        ControllerContext controllerContext = new ControllerContext(requestContext, Activator.CreateInstance(controllerType) as ControllerBase);
        ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
        ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, controllerContext.RouteData.Values["action"].ToString());
        return (actionDescriptor as ReflectedActionDescriptor).MethodInfo;
    }
}
Devin Garner
  • 1,361
  • 9
  • 20
  • Thank you! Spent all morning trying to figure this out. For other people's benefit I used this approach to get custom attributes for an action in a custom ACL provider for MvcSiteMapProvider. In that case I had access to RequestContext but not the full detail of an ActionExecutingContext as you'd get in a normal action filter. – Tim Croydon Nov 06 '12 at 11:47
  • 2
    The type names are normally not identical to the route name. For instance the type of the home controller is normally 'HomeController', which would not be matched by the first attempt to find the controller name, which would be 'Home' Furthermore, this disregards the use of areas. – Robert Sirre Feb 18 '15 at 13:11
2

Trying to work it out retrospectively is a bit of a can of worms, as you'd probably need to use reflection to discover the correct method - It would probably be simpler to insert the required data into the HttpContext.Items as part of the code where the authorization fails? It would then be available from your handling method through RequestContext.HttpContext.Items.

Stelloy
  • 2,316
  • 1
  • 19
  • 26
  • Worth noting that the life cycle of `HttpContext.Items` is per-request. Any information stored in the `Items Hashtable` will disappear after the request has executed. – Leigh Jun 18 '15 at 17:43
0

I have answered my own question, that is very similar to this.

If this is still of your interest, maybe I can go deeper into it.

My question didn't start from an URL as yours, but from controller and action names, and also the http method (GET, POST...).

Community
  • 1
  • 1
Miguel Angelo
  • 23,796
  • 16
  • 59
  • 82