Page 52 - MSDN Magazine, May 2019
P. 52
Cutting EdgE DINO ESPOSITO Routing and Route Templates in Blazor
A remarkable difference between the old days of ASP.NET Web Forms and the modern Web is the presence of a routing compo- nent at the gate of the Web server. In Web Forms, the vast majority of Web endpoints were physical file resources, invoked directly through their page path.
With ASP.NET MVC, a routing component kicks in whenever the requested URL can’t be mapped to a physical server file. The router takes the requested URL as an instruction to execute that has a client response as its output, whether an HTML view, a JSON payload, a binary stream or other output. The URL can also include optional parameters that help the router determine the specific content to present.
All Web development frameworks today have a routing compo- nent, and Blazor is no exception. In this article, I’ll explore the imple- mentation and programming interface of the Blazor routing engine.
The Routing Engine
The Blazor routing engine is a component that runs on the client side. It’s implementation, however, is made of C# code found in one of the assemblies downloaded in the browser and run through the WebAssembly processor. In Blazor applications, the router is currently configured in the app.cshtml file, like so:
<Router AppAssembly=typeof(Program).Assembly />
The following code shows the current content of the program.cs file. As you can see, at the moment it doesn’t include anything related to the router engine, but something is expected to happen later. Or at least, this is what the comment found in the Visual Studio autogenerated app.cshtml files suggests:
public static void Main(string[] args) {
Internally, the router builds up a table of routes and sorts them in a given order. The list of candidate routes results from the list of classes in the explored assemblies that implement the IComponent interface and, more importantly, are decorated with the Route attribute. All collected routes are stored in a dictionary sorted from the most specific to the least specific.
The evaluation algorithm is based on segments discovered in the URL and their position in the string. For example, a literal segment is more specific than a parameter segment, and in turn a parameter segment with more route constraints is considered more specific than others that present fewer constraints. Furthermore, as it hap- pens in ASP.NET MVC, when it comes to resolving a URL, routes in the table are evaluated from most to least specific and the search stops at first match.
Web development frameworks today have a routing component, whether they’re plain server environments such as ASP.NET Core or single-page application (SPA) frameworks.
On the client-side, the router engages in a number of situations, most commonly when the user clicks a link, a submit button on a form, or an item in a dropdown list that triggers a server call. The router binds to an internal location-changed event and handles— from the client side—the whole process of navigating to the newly requested path. Needless to say, the router kicks in also when the location of the application is changed programmatically. Last, but not least, the router logs in the browser history any location change it’s responsible for, so the back and forward buttons can work as users expect.
A War of Routers: Blazor vs. Angular
For a long time, the implementation of routing logic was buried in the folds of Web servers or server-side frameworks such as ASP.NET. It was with SPA frameworks—of which Angular is the
}
BrowserHttpMessageHandler.DefaultCredentials = FetchCredentialsOption.Include;
CreateHostBuilder(args).Build().Run();
public static IWebAssemblyHostBuilder CreateHostBuilder( string[] args) =>
BlazorWebAssemblyHost
.CreateDefaultBuilder() .UseBlazorStartup<Startup>();
The router class gets the provided assembly name and searches it, along with all referenced assemblies, for Blazor components that match the URL of the ongoing request. Note that this particular aspect of the router class behavior may evolve in the future toward a model where you have to explicitly specify the assemblies that you want the router to consider. That way you don’t accidentally end up with endpoints that you didn’t expect.
46 msdn magazine