FREELessons: 10Length: 1.5 hours

Next lesson playing in 5 seconds

  • Overview
  • Transcript

3.1 Defining Routes and Writing Controllers

The heart of any ASP.NET Core application is the URL routing engine, which routes incoming HTTP requests to the appropriate controllers. We’ll take a peek at it in this lesson.

Related Links

3.1 Defining Routes and Writing Controllers

In the previous lesson, I gave you an overview to an MVC application, and we've very briefly talked about routing. But in this lesson we're going to dive a little bit deeper because routing is probably the most important part of our application. It's how our application knows how to handle requests. And our routing table is defined inside of the Startup.cs file. If you go to the configure method on our startup class down here where we use in Nvc, this is where we set up our routes. So right now we have just one route. It's called default and it has a URL template. Now our URLs are relative to where our application lives. So if our application lives at localhost:5000, then all of our URLs are relative to that. So whenever we say controller/action/id, that would be controller/action/id. Now if our application lived at local host 5000/app, then all of our URLs would be relative to this local host at 5000/app. So let's, first of all, talk about where I got these values of controller/action/id. Well, inside of this template we have three segments. Our first segment looks a little funny. It has a pair of curly braces with controller=Home. Let's get rid of the equals sign just for this case here. We'll add all of this stuff back. But let's just have our template that says {controller}/{action}/{id}. What we have here are called URL parameters. These are placeholders for these segments of a real URL. So if we make a request for home/index/10, then this URL is going to match this template. And it's going take each segment of that URL and use that as a value for these placeholders. So home would be controller, index would be action and 10 would be id. But let's look at it like this. Let's say that we have products/edit/10. Well, products would be our controller, edit would be our action, and 10 would be id. So this URL would actually map to a method called Edit on a controller called Products Controller. Now all of our controllers end with the term controller. So if this was to be a valid URL, we would need to have a product's controller and it would need to have a method called Edit that would accept an id of 10. So if you'll remember in the previous lesson, whenever we ran this application, we didn't specify anything in the URL and we got the home page. But now that we've changed our routes, we removed the equal signs and all of that, we're going to get a different result. So let's do .NET run. Let's hop on over to our browser, and let's go to what we would think would be the home page. Well, we're going to get a 404. Now we get a 404, because we removed the default values for the controller and index segments. If you'll remember, we had controller=Home and then action=Index. Well, whenever you have a default value for any one of these placeholders, then you can essentially omit them. And if you omit them, then the default values would be used. So we could go back to the browser and we could explicitly say home and then index. But we're still going to get a 404 because the ID portion of our template also has to be defined as well. Now I didn't point it out whenever I removed the default values for home and action, but id had a question mark. That essentially means that that parameter is optional. So by changing this to optional, we could stop the server and restart it. And in fact, let's go ahead and take the time to set up the watchers so that we don't have to stop the server and then recompile and all of that stuff. So let's go to project.json and let's go down to the Tools section. Here we are going to add a tool called Microsoft.DotNet.Watcher.Tools, and then the version is going to be the version of everything else that we have here. This 1.0.0 preview for final. So we will just copy that and paste it in, and then we will need to run a dotnet restore. So let's hop on over to the command line, dotnet restore, hopefully everything will go by just peachy. And yes it did. So now we can say dotnet watch run. And then every change that we make to a C# file is going to automatically see that that file was updated. It's going to recompile so that we don't have to keep stopping and starting and all of that stuff. So let's go back. Now that we have id as optional, we can go to the browser. We can make a request for home/index. And here we have the home page. And the same is going to be true if we say home/about and so on and so forth. So as we make these segments optional by specifying a default value, then the less we have to actually specify within the URL. So if action is default index then we can omit that segment so that we just make a request 4/home, and there we have the index. So this default route that was given to us where controller defaults to home, action defaults to index and then id is optional, this is a good default route to have, because there are many URLs that are going to fit this pattern. For example, my example of products edit. And then 10 that fits right in there. In fact, let's go ahead and make this work. Let's create a product's controller. I'm going to use home controller as the basis. So we will need to copy and paste that file. We will change the name to ProductsController. And we also need to change the class name as well. We're gonna make some modifications to these methods. For example, the index is not going to return a view. Instead it's just going to return some text that says Products Index and we will need to change the return type. Now I think in the previous lesson I said that the action methods are methods that return I actual results and those methods are used to serve requests. And while that is true, that is not 100% true. Because really any public method on a controller can handle a request. There are a few cases where that's not the case, but you have to explicitly say that this method cannot handle requests. So if you see a public method on a controller that doesn't have anything that specifies that it can't handle a request then it can handle a request. So that is true for our index method that returns a string. And something like this is what you would see in an API controller, which is still a controller. In fact, there's really no difference between an MVC controller and an API controller. It's just how you go about using it. So an API controller, you would typically see just a return type of whatever data that method is supposed to return. But in our case, we're going to get away with just returning a string because we don't want to go through the process of creating a view just yet. So let's get rid of the about method and let's change the contact method to be edit. And we are also going to change the return type to string. And let's also accept an id value, although that needs to be called id. So that id parameter is also the name of the parameter for our method. So that's where that comes into play. And we are just going to return and say that this is product ID and then we will specify the id. So just like that. So let's save this, and let's go make some requests for our products controllers. So if we say products and we don't specify anything else, then that takes us to the index method, that's great. If we say edit/10, then we see Product ID and then ten. So we can see that our default route works very well. And it's going to match, I'm not going to say the majority of URLs because it really depends upon your application, but it's going to match the majority of URLs. Now let's say that instead of having products at a 10, let's say that we wanted to be more specific in our URL so that the actual type of product that we're editing would be part of the URL. So we would have products/guitar/edit/10. We could have products and let's say that we're something like Amazon where we sell everything. So we can have products/pizza/edit, and then whatever product is id 120 would be a pizza. So these two URLs don't really match this pattern. This pattern has at most three segments. These URL have four segments. So these aren't going to be caught by the default route. Instead, this is at a point where we need to define our own route. And really we're going to be using this type of scheme for all of our products. They are all going to start with the term products. So as you're defining your templates, you can use soft coded values for your segments like these URL parameters, or you can use hardcoded values as well. So let's call this products-route. That's going to be the name of this route, and for our template we're going to say that they all begin with products. So in a URL that begins with products is typically always going to be handled by this particular route. So then we're going to say our controller, we definitely need to know what our controller is so that we can get the right controller for our products. But the action method is going to be optional. So we can set the default value to index. And then id is definitely going to be optional. And I guess I shouldn't say that action is optional because we definitely need an action there. But it's just that we have a default value of index. So it's easy to say that this is an optional thing. And so now let's write a guitars controller. And we're going to use our products controller as a basis because that already has everything set up. We just need to make a few changes so that we know that we are doing something off of the guitars controller. So let's copy products controller. Paste it and let's rename that to guitars controller. We'll change the name of the class to guitars controller. And instead of the index method, we're going to say Guitars index and we'll also say Guitars or Guitar ID, rather, inside of Edit. And so with those changes, let's save. Let's hop on over to the browser. And let's make a request for products/edit/10. Let's see what we get. We still get the same thing. And if we say products/guitars/edit/10, then we get Guitar ID: 10. So the basic routing concepts are very simple to grasp. You define a route by specifying a template that's used to match against the request URLs that are coming in. If the routing engine finds a match, then it routes that request to a method on a controller. But if it doesn't, then it just returns a 404. Now I should say that we just barely scratched the surface of routing in MVC. The routing engine is very flexible and very robust. There are a lot of wonderful features that you can take advantage of. One of those is attribute routing, so that instead of defining your routes in a routing table inside of the startup class, you define them as attributes on your controllers. So I encourage you to look into that. I will provide some links in the description for this video so that you can read up more on that feature. But we need to keep trucking on, so in the next lesson we are going to talk about views.

Back to the top