Get controller name

10,052

As confirmed by @KiranChalla there is no simpler way then the one I've already implemented, except the minor suggestion to use GetSubRoutes()

var attributedRoutesData = request.GetRouteData().GetSubRoutes();
var subRouteData = attributedRoutesData.FirstOrDefault();

var actions = (ReflectedHttpActionDescriptor[])subRouteData.Route.DataTokens["actions"];
var controllerName = actions[0].ControllerDescriptor.ControllerName;
Share:
10,052
Matija Grcic
Author by

Matija Grcic

AWS Certified Alexa Skill Builder – Specialty AWS Certified Solutions Architect - Associate Professional Scrum Master level I (PSM I) Microsoft Certified Solutions Developer (MCSD) Web Applications Microsoft Certified Technology Specialist (MCTS) Areas of interest C# language specification Javascript TypeScript ASP.NET MVC ASP.NET Web API Exception driven development by knowing more about your application's health than your customers do so you're not waiting around for customers to tell you about problems with your system. Customer (complaint) driven development by identifying the top things customers complain about most in your software, and fixing those things.

Updated on July 19, 2022

Comments

  • Matija Grcic
    Matija Grcic almost 2 years

    In WebApiConfig.cs i have the following

    public static void Register(HttpConfiguration config)
    {
    
       config.MapHttpAttributeRoutes(); 
    
       config.Services.Replace(typeof(IHttpControllerSelector),
                   new MyApiControllerSelector(config));
    
       //code omitted for brevity
    }
    

    then in the MyApiControllerSelector.cs i want to get the controller

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {           
                var routeData = request.GetRouteData();           
    
                var controllerName = (string)routeData.Values["controller"];
    
                //code omitted for brevity
            }
    

    Pretty simple and it worked great but now using attribute routing i think it needs a different approach? - as i can't seem to find a simple way

    I've tried

    var controllerName = request.GetActionDescriptor().ControllerDescriptor.ControllerName;
    

    which doesn't work.

    Then reading the source with debugging lead me to request.GetRouteData().Values["MS_SubRoutes"]

    So now I have

    string subRoutesKey = "MS_SubRoutes";
    
    var attributedRoutesData = routeData.Values[subRoutesKey] as IEnumerable<IHttpRouteData>; 
    var subRouteData = attributedRoutesData.FirstOrDefault();
    
    var actions = (ReflectedHttpActionDescriptor[])subRouteData.Route.DataTokens["actions"];
    var controllerName = actions[0].ControllerDescriptor.ControllerName;
    

    which works but it has to be a simpler way?

    UPDATE

    @KiranChalla asked what's my use case so i'm posting the remaining code. Basically i'm parsing version media type Accept: application/vnd.app.{resource}.v{version}+json from request and returning a HttpControllerDescriptor depending on the version.

                HttpControllerDescriptor oldControllerDescriptor;
                if (controllers.TryGetValue(controllerName, out oldControllerDescriptor))
                {
                    var apiVersion = GetVersionFromMediaType(request);
    
                    var newControllerName = String.Concat(controllerName, "V", apiVersion);
    
                    HttpControllerDescriptor newControllerDescriptor;
                    if (controllers.TryGetValue(newControllerName, out newControllerDescriptor))
                    {                    
                        return newControllerDescriptor;
                    }               
                    return oldControllerDescriptor;
                }
                return null;
    
  • Matija Grcic
    Matija Grcic over 10 years
    @ainteger No, it's just a different approach to get the necessary data (controller name) from the pipeline.
  • BitMask777
    BitMask777 almost 9 years
    The suggestion of using GetSubRoutes() is an excellent one. It's the approach I've taken because using MS_SubRoutes is reliance on an undocumented string literal that could easily change without warning in the future.