Web API Routing - The Basics

November 05, 2017

Working with API projects, it’s easy to miss some key rules about the routing. This post is basically the result of some that I missed, and subsequent the investigation. It covers some very basic routing rules, and it certainly not intended to be an exhaustive guide.

.Net Framework

Starting with a .Net Framework Web API, let’s create a new web app:

routing 1

And add a new controller:

routing 2

Here’s the code for the controller; as you will see, it’s massively complex, but the good news is that you only need to pay attention to the name of the action, and the code inside it:



public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult TestAction()
    {
        return Ok("TestAction Performed");
    }
}

Let’s run the project and navigate to the URL:

routing 3

How did I know that was the URL? It’s magic, and you can buy some of that magic by sending a cheque for the low, low price of $25 to the address shown at the bottom of the screen.

Actually, it’s defined in WebApiConfig.cs:

routing 4

Parameters

Where there is more than a single function, one surprising (to me) feature is that the parameters that it accepts is more important to the routing than the name of the controller. Here’s a second action with a parameter:



[HttpGet]
public IHttpActionResult TestAction2(string test)
{
    return Ok("TestAction2 Performed");
}

… and here’s it working:

routing 5

However, should I not give it the parameter that it craves, it hides away, and instead, we get the first function that’s no too fussy about parameters:

routing 6

It doesn’t even matter whether I just put some drivel as the controller name; the first criteria is the parameter:

routing 7

This is because, according to this it follows these criteria:

The default implementation is provided by the ApiControllerActionSelector class. To select an action, it looks at the following: • The HTTP method of the request. • The “{action}” placeholder in the route template, if present. • The parameters of the actions on the controller.

So, if we add the {action} placeholder, that ensures that it uses the correct method:



public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
 
    // Web API routes
    config.MapHttpAttributeRoutes();
 
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        //routeTemplate: "api/{controller}/{id}",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Otherwise, we get a best guess based on the parameters.

.Net Core Web API

The rules have changed since switching to .Net Core; WebApiConfig has gone and, in its place, it a localised routing system.

Here, you tell the class how to handle routing; for example, the following:



[Route("api/[controller]")]

Will result anything decorated with HttpGet being called when the controller is called. The parameters must be explicitly decorated; so passing no parameters would look like this:




[HttpGet]
public string OneTest()
{
    return "TestOne";
}

Whereas, a single parameter would look like this:




[HttpGet("{id}")]
public string aaa(int id)
{
    return "value aaa";
}

If you duplicate the signatures then they are not found. As with the framework version, you can simply tell it to look to the action name that you give it:



[Route("api/[controller]/[action]")]
public class TestController : Controller
{
    [HttpGet]
    public IEnumerable<string> TestActionOne()
    {
        return new string[] { "one value1", "value2" };
    }
 
    [HttpGet]
    public string TestActionTwo()
    {
        return "two value";
    }

But, again, it pays no attention to parameters until you decorate it correctly.

References

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024