Search code examples
c#asp.netasp.net-mvc-4asp.net-web-apiasp.net-web-api-routing

How Do I Support Empty RouteAttribute in Web API?


I have this class:

[RoutePrefix("api/v2/Foo")]
public class SomeController : BaseController
{
    [Route("")]
    [HttpGet]
    public async Task<HttpResponseMessage> Get(SomeEnum? param)
    {
        //...
    }
}

I want to call it via: api/v2/Foo?param=Bar but it doesn't work.

If I change the routing attribute thusly to include something in the RouteAttribute:

    [Route("SomeRoute")]
    [HttpGet]
    public async Task<HttpResponseMessage> Get(SomeEnum? param)
    {
        //...
    }

...then I can call api/v2/Foo/SomeRoute?param=Bar , but that isn't what I want.

How do I get the first circumstance to work?

EDIT: Domas Masiulis steered me toward the answer: the above scenario DOES work, it's just that a default global routing screwed things up. I solved the issue by adding a separate default routing that matched our convention...

    public static void RegisterRoutes(RouteCollection routes)
    {
        //ADDING THIS FIXED MY ISSUE
        routes.MapHttpRoute(
            name: "API Default",
            routeTemplate: "api/v2/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        //SOURCE OF THE ORIGINAL PROBLEM
        routes.MapRoute(
           "Default", // Route name
           "{controller}/{action}/{id}", // URL with parameters
           new { controller = "Administration", action = "Index", id = UrlParameter.Optional } // Parameter defaults
       );
    }

Solution

  • Any special conditions? Maybe something hidden in BaseController? Any custom configurations in RouteConfig?

    Your given example works for me, made a quick test:

    Used code:

    [RoutePrefix("api/v2/Foo")]
    public class SomeController : ApiController
    {
        [Route("")]
        [HttpGet]
        public Task<int> Get(int param)
        {
            return Task.FromResult(2);
        }
    }
    

    Calling http://localhost:1910/api/v2/Foo?param=1 works as expected - returns 2.