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

Web Api Attribute Routing with optional parameters and query parameters


I have this web api controller :

[RoutePrefix("api/product")]
public class ProductController : ApiController
{
    [HttpGet, Route("{id?}")]
    public async Task<HttpResponseMessage> GetProduct([FromUri] string param1 = null, [FromUri] string param2 = null, Guid? id = null)
    {
        ...     
    }
}

I would like to access by those uri :
api/product/?param1=something&param2=smt
or
api/product/7b55fcee-21e7-4b10-80e3-42b4d9cf913d?param1=something&param2=smt

However, the first uri does not work, default value for route parameter is not set.
This uri works :
api/product/null?param1=something&param2=smt
not this one :
api/product/?param1=something&param2=smt

I tried to use the type "string" for the route parameter but it still didn't work.

Is it the order of parameters ?
Or did I misunderstood something about Web Api Route Mapping ?

EDIT : My WebApiConfig.cs does not contains default routes :

public static class EdmWebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
       if (config == null) throw new ArgumentNullException(nameof(config));

       // Attribute routing
       config.MapHttpAttributeRoutes();

       ...
       some declaration of formatters
       ...
    }
}

Should I declare a default route ?
In my opinion, since I use Attribute mapping, I don't need to do that.

I tried to change my routing like that :

[RoutePrefix("api")]
public class ProductController : ApiController
{

    [HttpGet, Route("product/get/{id?}")]
    public async Task<HttpResponseMessage> GetProduct([FromUri] Guid param1, [FromUri] string param2, Guid? id = null)
    {
      ...
    }
}

This uri api/product/get/?param1=something&param2=smt still does not work.
(I tried api/product/?param1=something&param2=smt with the associated routing, not working)

Do I need to declare default route in my WebApiConfig.cs ?
What you can do in WebApiConfig.cs, you should be able to do it in attribute routing, isn't it ? Like optional parameters, constrainsts,...


Solution

  • Your route prefix is too specific. I believe you want:

    [RoutePrefix("api")]
    public class ProductController : ApiController
    {
        [HttpGet, Route("product/{id?}")]
        public async Task<HttpResponseMessage> GetProduct([FromUri] string param1 = null, [FromUri] string param2 = null, Guid? id = null)
        {
            ...     
        }
    }
    

    Which should work well for you. A route prefix is not a route in-and-of itself, so the default route should be less specific.