Page 54 - MSDN Magazine, May 2019
P. 54
king—that router implementations moved to the client. Let’s take a moment to run a brief comparison of the features in the consol- idated Angular router and the still in-the-works router of Blazor.
The bottom line is that the Blazor router at the moment only provides basic functionality as a client-side router. For instance, it lacks the ability to check authorizations on a route and create links that perform view transitions when the location changes. And un- like the Angular router, it cannot work asynchronously to run the resolve step after obtaining route parameters. Finally, the Blazor router lacks support for conditional redirection to alternate routes— something, again, that the Angular router can do.
It’s reasonable to expect that part of this delta will be reduced by the time Blazor ships as version 1.0.
Route Templates
Routing is the process that binds together a URL with a list of known URL patterns. In Blazor, URL patterns, or route templates, are collected in a route table. The table is populated by looking at the components of the Blazor application decorated with the Route attribute. The path to each of those components becomes a supported route template.
At the moment, there’s just one way for developers to control the route path of reachable components: the @page directive. In ASP.NET Core, for example, a developer can define routes explic- itly by adding them to the table programmatically, letting the system figure out candidates using the default route conventions or using attributes on controller methods. If you use Razor pages in ASP.NET Core applications, then you go through exactly the same experience as a Blazor developer—the @page directive.
In summary, each and every Blazor component must specify its route template through the @page directive to be reachable. A Blazor component is made of a .cshtml file that’s compiled into a C# class that implements the IComponent interface. The same dynamically compiled class is also decorated with the Route attri- bute if the Razor source contains the @page directive.
It’s interesting to note that Blazor supports multiple route directives in the same view. In other words, the following code is well supported:
@page “/”
@page “/home”
<h1>My Home Page</h1>
All routes discovered are put in the same route table container and sorted according to the aforementioned rules. In the previous sample, both route directives are made of literals, so they both go in the top area of the final container and are sorted in order of (relative) appearance.
Routes do support parameters, and a parametric route is recog- nized at a lower priority in the final table than literal routes, as it’s considered less specific. Here’s an example of a parametric route:
@page “/user/view/{Id}”
The URL pattern-matching algorithm triggers for this route when the URL comprises the server name followed by /user/view/. Any content in the URL that trails /user/view/ is associated with the named parameter {Id}.
If you’re familiar with ASP.NET MVC (and to a good extent even Web Forms), this model-binding pattern should be old hat. In ASP.NET, route parameters are assigned to the formal parame-
ters of the matched controller method. In Blazor, things are slightly different but comparable.
In Blazor, router parameters are automatically assigned to the prop- erties of the component annotated with the [Parameter] attribute. The matching occurs on the names of parameters and properties. Here’s a quick example:
@page “/user/view/{Id}”
<h1>Hello @Id!</h1>
@functions {
[Parameter]
public string Id { get; set; }
protected override void OnInit() {
// Some code here }
At the moment, Blazor doesn’t support optional parameters, so if {Id} in the sample URL is missing, the entire URL isn’t matched. To avoid this, the best current workaround is to have two @page direc- tives, with and without the parameter, as shown in the following code:
@page “/user/view/{Id}” @page “/user/view/”
<h1>Hello @Id!</h1>
@functions {
[Parameter]
public string Id { get; set; } = “0”;
protected override void OnInit() {
// Some code here }
}
At the same time, you might also want to give the bound page parameter a default that’s overridden if a value is passed via the URL.
It should be noted that while the Blazor router can be triggered by links, it can also be triggered programmatically.
Type matching is a common problem with parametric routes and automatic binding to variables. If the segment of the URL contains a literal string, but the bound variable is declared of type int, what hap- pens? In normal conditions, without any precaution, it probably yields an exception, as a literal value is stuffed into an integer container. If you need to make sure that only values of a given type are specified where a parameter is expected, you should opt for route constraints.
A route constraint is nothing new if you’re familiar with any flavor of ASP.NET MVC. It consists of adding a type attribute to each URL parameter, as shown here:
@page “/user/view/{Id:int}”
The name of the parameter is followed by a colon symbol and a literal that refers to a .NET type. Supported literals match one-to- one most of the .NET primitive types: int, bool, double, float, date- time, long and decimal. For routes with constraints, any parameter
48 msdn magazine
Cutting Edge
}