You can easily tell from the last post that routing and executing endpoints are at the core of ASP.NET Core. The routing is not so difficult to grasp, you just need to remember the syntaxes.
To start, if you are building a Razor Page website, which has a page to show product detail, you may want to create a page: Pages/Products/Detail.cshtml
. The page may have the following directive on its first line:
@page "products/detail/{category}/{id}/{color}"
With this information, the framework’s routing component will route the request to www.example.com/products/detail/shoes/5/red
to this Razor Page’s handler.
Note that it’s using the location of the file plus the @page
directive to determine the destination. By default, the router starts from the Pages
folder, and treat every nested folder as a segment in the URL. So the products/detail
segments in the URL will be mapped to Pages/Products/Detail.cshtml
. But that’s not the end of story yet. If you try to visit the URL www.example.com/Products/Detail
, it will not be mapped to the Detail.cshtml
, because the {category}/{id}/{color}
segments in the directive is still missing. These segments in the {}
is the required dynamic data.
Before we dive into what the dynamic data are for, it’s worth mentioning that we always need the @page
directive on the first line for normal Razor Pages that you want to be the target of the routing system. This also means pages like layout and partial views should not starts with the @page
directive, as they are not the destinations for any routing.
So, what are the {category}/{id}/{color}
? In short, they are part of the URL carrying dynamic data that will be used for model binding.
When the URL www.example.com/products/detail/shoes/5/red
is requested, the Detail
page is selected as the destination. Then the framework’s model binder parses the rest of the URL as values for the pages’ binding model, in our case:
- category = shoes
- id = 5
- color = red
To get the binding working, there are two approaches:
- Add parameters to the handler method:
public class DetailPageModel : PageModel {
public string Category {get; set;}
public int Id {get; set;}
public string Color {get; set;}
public void OnGet(string category, int id, string color){
Category = category;
...
}
}
- Use the
[BindProperty]
attribute, which only works for POST request unless you specify GET support in the attribute:
public class DetailPageModel : PageModel {
[BindProperty(SupportsGet = true)]
public string Category {get; set;}
[BindProperty(SupportsGet = true)]
public int Id {get; set;}
[BindProperty(SupportsGet = true)]
public string Color {get; set;}
...
}
Once the model binding is done, the Razor page can access the model with the directive:
@model DetailPageModel
For example, with Razor engine, the page can display the category of the product like: <h1> Look at my @Model.Category </h1>
, which will be transformed to <h1> Look at my shoes </h1>
in the response.