Search code examples
c#asp.net-web-apiquery-stringasp.net-web-api-routingattributerouting

Query string not working while using attribute routing


I'm using System.Web.Http.RouteAttribute and System.Web.Http.RoutePrefixAttribute to enable cleaner URLs for my Web API 2 application. For most of my requests, I can use routing (eg. Controller/param1/param2) or I can use query strings (eg. Controller?param1=bob&param2=mary).

Unfortunately, with one of my Controllers (and only one), this fails. Here is my Controller:

[RoutePrefix("1/Names")]
public class NamesController : ApiController
{

    [HttpGet]
    [Route("{name}/{sport}/{drink}")]
    public List<int> Get(string name, string sport, string drink)
    {
        // Code removed...
    }

    [HttpGet]
    [Route("{name}/{drink}")]
    public List<int> Get(string name, string drink)
    {
        // Code removed...
    }
}

When I make a request to either using routing, both work fine. However, if I use a query string, it fails, telling me that that path does not exist.

I have tried adding the following to my WebApiConfig.cs class' Register(HttpConfiguration config) function (before and after the Default route), but it did nothing:

config.Routes.MapHttpRoute(
name: "NameRoute",
routeTemplate: "{verId}/Names/{name}/{sport}/{drink}",
defaults: new { name = RouteParameter.Optional, sport = RouteParameter.Optional, drink = RouteParameter.Optional },
constraints: new { verId = @"\d+" });

So for clarity, I would like to be able to do both this:

localhost:12345/1/Names/Ted/rugby/coke
localhost:12345/1/Names/Ted/coke

and,

localhost:12345/1/Names?name=Ted&sport=rugby&drink=coke
localhost:12345/1/Names?name=Ted&drink=coke

but sadly the query string versions don't work! :(

Updated

I've removed the second Action altogether and now trying to use just a singular Action with optional parameters. I've changed my route attribute to [Route("{name}/{drink}/{sport?}")] as Tony suggested to make sport nullable, but this now prevents localhost:12345/1/Names/Ted/coke from being a valid route for some reason. Query strings are behaving the same way as before.

Update 2 I now have a singular action in my controller:

[RoutePrefix("1/Names")]
public class NamesController : ApiController
{

    [HttpGet]
    [Route("{name}/{drink}/{sport?}")]
    public List<int> Get(string name, string drink, string sport = "")
    {
        // Code removed...
    }
}

but still, using query strings does not find a suitable path, while using the routing method does.


Solution

  • After much painstaking fiddling and Googling, I've come up with a 'fix'. I don't know if this is ideal/best practice/plain old wrong, but it solves my issue.

    All I did was add [Route("")] in addition to the route attributes I was already using. This basically allows Web API 2 routing to allow query strings, as this is now a valid Route.

    An example would now be:

    [HttpGet]
    [Route("")]
    [Route("{name}/{drink}/{sport?}")]
    public List<int> Get(string name, string drink, string sport = "")
    {
        // Code removed...
    }
    

    This makes both localhost:12345/1/Names/Ted/coke and localhost:12345/1/Names?name=Ted&drink=coke valid.