1

I have an ASP.NET Web API application where I want to respond to the following routes:

1. http://localhost:1234/values
2. http://localhost:1234/values/123
3. http://localhost:1234/values/large
4. http://localhost:1234/values/small

Note: These routes and examples are just that, examples. But they map to what I want achieve.

  1. Should return all values, say a list of numbers.
  2. Should return the value of the resouce with id 123.
  3. Should return a list of what the app considers large values. Whatever that may be.
  4. Should return a list of what the app consider small values.

As with a billion ASP.NET Web Api routing examples, number (1) and (2) are straightforward. But when I try and resolve (3) and (4), then (1) and (2) are no longer working.

This is the routes I have at the moment:

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // trying to map to "values/large" or "values/small"
        routes.MapHttpRoute(
            name: "ActionsApi",
            routeTemplate: "{controller}/{action}",
            defaults: null,
            constraints: new { action = @"^[a-zA-Z]+$" }
        );

        // trying to map to "values/123"
        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{controller}/{id}",
            defaults: null,
            constraints: new { id = @"^\d+$" }
        );

        // trying to map to "values"
        routes.MapHttpRoute(
            name: "ControllerApi",
            routeTemplate: "{controller}"
        );

With the above routes, (3) and (4) work.

(2) returns:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
No action was found on the controller 'Values' that matches the name '123'.
</string>

And (1) returns:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
Multiple actions were found that match the request:
System.Collections.Generic.IEnumerable`1[System.String] Get() on type MvcApplication3.Controllers.ValuesController
System.Collections.Generic.IEnumerable`1[System.String] Large() on type MvcApplication3.Controllers.ValuesController
System.Collections.Generic.IEnumerable`1[System.String] Small() on type MvcApplication3.Controllers.ValuesController
</string>

I am at a loss as to how to setup the routes to support the 4 API examples I listed above.

EDIT: Thanks to David, he pointed out that \w also matched digits, hence a problem. I changed it to [a-zA-Z]+ to match large and small.

Now all work except for (1).

EDIT 2 As suggested by @andrei I made the id parameter optional, to try and get (1) working, but resulted in the following error for that route:

The resource cannot be found.

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly. 

The optional default I added here:

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"^\d+$" }
        );
2
  • 123 looks like it is a match for regex ^\w+$. Commented Jun 13, 2013 at 8:15
  • @DavinTryon oh! silly me! I thought \w matched only letters (as in words). Also includes digits. Thank you, David. Commented Jun 13, 2013 at 8:18

1 Answer 1

1

Have you considered leaving the routing as default, and dealing with the "values" in your controller?

e.g. Change your Get to make id of type string, then check for "special" values inside your controller.

public class ValuesController : ApiController
    {

    // GET api/values/5
    public string Get(string id)
    {
        if (id == "large")
        {
            return "large value";
        }

        if (id == "small")
        {
            return "small value";
        }

        return "value " + id;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I will use this method, then calling worked functions depending on the value of id – whether it be an int, or a string like "large" or "small".

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.