11

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;
5
  • 2
    I believe there is no other simpler way that I am aware of. Just fyi...a small improvement, you can do request.GetRouteData().GetSubRoutes() to get list attribute routes... Commented Oct 23, 2013 at 17:42
  • By the way, Can you describe what your scenario is? I am curious to know how you intend to use custom controller selector with attribute routing. Commented Oct 23, 2013 at 17:48
  • @KiranChalla Thanks for the suggestion. I've explained my scenario and added the remaining code so please take a look and correct me if i'm doing anything wrong. Commented Oct 24, 2013 at 6:55
  • @KiranChalla can you take a look at stackoverflow.com/questions/19835015/… Commented Nov 8, 2013 at 15:02
  • Curiously, DefaultHttpControllerSelector has a GetControllerName method that also fails on sub routes. Commented Mar 30, 2014 at 18:34

2 Answers 2

14

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;
Sign up to request clarification or add additional context in comments.

2 Comments

@ainteger No, it's just a different approach to get the necessary data (controller name) from the pipeline.
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.
0

its old ticket but i get controller name this way,

 var ControllerName = context.Request.RouteValues.Keys.FirstOrDefault();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.