Learn how to create multiple routes in your routing table.
- [Instructor] So we saw earlier, the default routing mechanism in Web API is the route's table. In its default configuration, there is a single route that goes to /api/controller/id just like our route here defined on line 34. Let's customize our routing table so you can seen an example of when you might wanna add more routes to your application. Here's the single routing rule that we were using earlier which I just mentioned. With this rule in mind, let's go to the TourController and create the need for another rule.
We already have a single get method here in the TourController on line 17. It allows us to get a list of all tours or at least all tours where the price is free if we pass in the optional parameter. But let's add a second get method that takes a single parameter of type int and we'll call it id. We'll do the same basic query that we did above, so I'll copy that.
But now we're going to filter it a little differently. We're going to filter it with a Where, where the TourId is equal to the id that was passed in, in the request. And then we'll take the first or default item that comes back, the default being null in this case for an object, and we'll call that variable item. And then we'll return that item.
Now with our updated app running, we'll go back to Postman and let's hit /api/tour with a get request and when we do that, you'll notice that it still returns all the tours. So it's still hitting our original get all method. If I put an id at the end of the path and submit the request again, you can see that it is now hitting our new id-based get method which returns just the first item with the id of one from the Tours table.
If we look at the startup class again, we can see why this happens. Remember that our one and only routing rule has an optional id parameter at the end. This easily matched our method with a single id parameter called id. So it ran even our new action method for us. Now let's create a third get method, which to start with, I will copy from the one we just created.
And I'll change the name to GetByName and I'm going to change the parameter from an integer to a string with the word name. And then instead of searching based off of TourId, let's search based off of name where the name contains the name that was specified in the request. And once again we'll still match the first one we find and return it as a tour. If we hit the /api/tour endpoint with a get, you can see that it still works as it did before.
How about the tour with an id endpoint? And yes that does in fact work as expected. Now let's try our new one and we'll send in the word backpack here as part of the name. You'll notice that it gives us an error for this. You can see in the error message that it's matching the get method that takes an integer id of int 32 and not the one that takes a string parameter that we just created.
Why is it doing that? If we look back at our single routing rule, remember that it's looking for something at the end of the path after the controller name, but that something has no constraints on it whatsoever. It could be an integer or a string or anything else. This route matches our controller method that takes a string and our controller method that takes an integer. Let's fix this by creating a constraint on this rule and adding second rule.
We can add a constraint to this rule by specifying a new constraint object here and we'll say that we want our id to match \d which is the regular expression for a digit character and then plus, which is the regular expression to mean zero or one instances of that. Or in other words, we're looking to match zero to nine many times at least once. Anything else that's specified in this part of the route will not match this routing rule.
Now that this first route only matches our get method that takes an integer and not the one that takes a string, let's add a second route to match all other get methods. We can copy our previous rule, but we need to change the name. So let's change the name from DefaultApi to DefaultNameApi. And I'll change id here to name throughout and remove the constraint that we just added for the first rule.
Now this rule will match our latest get method that we added with the string name parameter. To test this out in Postman, let's do the same request we did before, /api/tour/backpack. This time, when we submitted the request, you can see that we get back the Backpack Cali tour, just like we wanted. Changing the backpack to a two, still successfully works at hitting our get by id method and removing the end still hits our get all method successfully.
So now we have a second rule that works the way wanted without interfering with that first rule. We've seen how to use the routing table to create multiple routes that can match our controlled actions in different situations. And we've seen how to add constraints to our routes to control those requests that are matched.
- Convention-based routing
- Binding your code to an HTTP request
- Validating models
- Using attributes to route requests
- Customizing attribute routes
- Data serialization and model binding
- Error handling
- Using exception filters and exception loggers
- API documentation and testing
- Securing your API