2

I have the following WebAPI controller:

namespace MyApp.WebApi.Controllers
{
    [RoutePrefix("api/listing")]
    public class ListingController : ApiController
    {
        [Route("{firstparam:int?}/{nextparam:int?}")]
        public IEnumerable<ListItem> Get(int firstparam = 100, int nextparam = 12)
        {
             // firstparam is always 100, and nextparam is always 12

However, I've tried specifying the URL:

http://localhost:56004/#/listing?firstparam=2

If I specify the URL like this:

http://localhost:56004/#/listing/2

Then it breaks the routing.

Clearly I'm missing something regarding routing; please could someone point me in the right direction?

2 Answers 2

1

You are using multiple optional parameter which don't work well for routeTemplates. Normally the last parameter tends to be the optional parameter.

Documentation: Attribute Routing in ASP.NET Web API 2: Optional URI Parameters and Default Values

FIrst make sure the attribute routing is enabled

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Attribute routing.
        config.MapHttpAttributeRoutes();

        // Convention-based routing.
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

To get what you are after

[RoutePrefix("api/listing")]
public class ListingController : ApiController {

    //GET api/listing
    //GET api/listing?firstparam=x
    //GET api/listing?nextparam=y
    //GET api/listing?firstparam=x&nextparam=y
    [HttpGet]
    [Route("")]
    public IEnumerable<ListItem> Get(int firstparam = 100, int nextparam = 12) { ... }
}

The problem with having multiple inline parameters that are optional is that the router wont know which to use which is why they tend to be at the end of the url.

However to get them inline like how you mentioned in your example you are going to need multiple routes.

[RoutePrefix("api/listing")]
public class ListingController : ApiController {

    //GET api/listing
    [HttpGet]
    [Route("")]
    public IEnumerable<ListItem> Get() { return Get(100, 12);  }

    //GET api/listing/2
    //GET api/listing/2/5
    [HttpGet]
    [Route("{firstparam:int}/{nextparam:int?}")]
    public IEnumerable<ListItem> Get(int firstparam, int nextparam = 12) { ... }
}
Sign up to request clarification or add additional context in comments.

Comments

0

You could try using [FromUri] attribute within the params of the Get() method to extract any query params being passed into the "/listing" uri along with a class that consists of int properties firstparam and secondparam.

namespace MyApp.WebApi.Controllers
{
    [RoutePrefix("api/listing")]
    public class ListingController : ApiController
    {
        [Route("")]
        [HttpGet]
        public IEnumerable<ListItem> Get([FromUri] ClassRepresentingParams params)
        {

Hopefully that helps.

5 Comments

What would the URL for that look like? It just seems to break the routing (that is, it doesn't find Get)
Try adding an [HttpGet] attribute to the method as well. I've updated my answer.
HttpGet("") doesn't compile. Without the quotes it makes no difference, I still lose the routing
it's [HttpGet] only.
The configuration for the project may not be set up correctly for attribute based routing. This may be preventing routes from compiling. Within your WebApiConfig class you'd need config.MapHttpAttributeRoutes(); within the Register() method.

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.