Blazor Server Navigation

A Guide to Passing Parameters in Razor Pages

5 min readMar 8, 2024

--

Introduction

In Blazor Server development, passing parameters into razor pages is key to dynamic page rendering. This guide explores two main methods — through direct routes and HTTP query strings — using the universal language of chocolate to demystify the process 🍫.

Why is it important, you ask?

  1. Embedding parameters directly into the URI ensures a consistent and stateful experience for users.
  2. It simplifies bookmarking and sharing links, as the URL contains all necessary data to render the same page with the same set of data.
  3. It aids in creating a cleaner and more organized web structure, where each URL is a direct reflection of the content it leads to.

We’ll explore the advantages/disadvantages of each method, and how each method can be leveraged to create a rich, engaging user experience that leaves a lasting impression, just as a perfectly crafted piece of chocolate does.

Method 1: Using Parameters in Page Route

In Blazor Server, defining parameters directly in the page route is a method that allows for clarity in delivering content.

Let’s apply this to a deliciously specific example: navigating to a page with the details of a chocolate manufacturer.

Here’s how you can define a route parameter in your Blazor page for such a purpose:

@page "/chocolate/manufacturer/{ManufacturerId:guid}"

@code {

[Parameter]
public Guid ManufacturerId { get; set; }

}

In this scenario, ManufacturerIdis a parameter of type Guid that we’re expecting to receive. An example of this URL in action could be something like:

https://your-domain.com/chocolate/manufacturer/e87a53f8-760e-4d87-a681-37f3a50f424c

This can be expanded to accommodate passing in multiple properties. Let’s extend our example: navigating to a page with the details of a specific product from a chocolate manufacturer.

Here’s how you can define a route parameter in your Blazor page for such a purpose:

@page "/chocolate/manufacturer/{ManufacturerId:guid}/product/{ProductId:guid}"

@code {

[Parameter]
public Guid ManufacturerId { get; set; }

[Parameter]
public Guid ProductId { get; set; }

}

An example of this URL in action could be something like:

https://your-domain.com/chocolate/manufacturer/e87a53f8-760e-4d87-a681-37f3a50f424c/product/af664c94-6fce-45f6-b675-962e935fe29f

Once again, you can see how properties becomes part of the route for the page and therefore cannot be omitted.

Advantages:

🧼 Clean URLs: Parameters are part of the URL path, resulting in cleaner and more readable URLs. It’s like having a neatly labelled chocolate box where you know exactly what you’re picking.

💪 Strong Typing: Parameters can be strongly typed, much like ensuring only the highest quality cocoa is used. This ensures that the data passed matches the expected type, reducing the risk of unexpected surprises.

🪄Automatic Property Matching: Blazor server will automagically find the parameter data within the URI and populate the respective parameter field in the code block of your razor file.

Disadvantages

🙉 Limited Flexibility: This approach is best suited for mandatory parameters. Missing parameters here will result in a route mismatch and being redirected to a generic error page (i.e. page not found).

🤔Unintuitive Querying: Values for parameters are passed in the URL but it is not really intuitive as to what properties those parameters are filling. Further, you cannot omit properties in querying.

Method 2: Using NavigationManager and QueryHelpers

There is another method that follows the standard guidelines for HTTP querying in the URL. In this method flexibility is key. In Blazor Server applications, passing parameters via the query string offers a more familiar and adaptable approach to data transmission.

To effectively navigate and parse these dynamic parameters, we employ the NavigationManager service and QueryHelpers namespace.

Consider a scenario where you want to filter chocolate products by both manufacturer and product ID. Your URL might look something like this:

https://your-domain.com/chocolate?manufacturerId=e87a53f8-760e-4d87-a681-37f3a50f424c&productId=af664c94-6fce-45f6-b675-962e935fe29f

In this example, the query string contains parameters for both manufacturerId and productId. Here's how you can extract these parameters using Blazor's tools:

@using Microsoft.AspNetCore.WebUtilities;
@inject NavigationManager Navigation;
@page "/chocolate"

@code {

[Parameter]
public Guid? ManufacturerId { get; set; } = null;

[Parameter]
public Guid? ProductId { get; set; } = null;

protected override void OnInitialized()
{
// get URI
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);

// Note: QueryHelpers is part of the Microsoft.AspNetCore.WebUtilities package.
var queryParameters = QueryHelpers.ParseQuery(uri.Query);

// try get ManufacturerID
if (queryParameters.TryGetValue(key: "manufacturerId",
value: out var manufacturerId))
{
ManufacturerId = Guid.Parse(manufacturerId);
}
// try get ProductID
if (queryParameters.TryGetValue(key: "productId",
value: out var productId))
{
ProductId = Guid.Parse(productId);
}
}

}

A few important things to note here are that:

  • The parameters have default null values. This allows us to omit them if not necessary (this was not possible in the prior method).
  • The parameters are set in the OnInitialized() method. Obviously, this could be done with OnInitializedAsync() if required and with better handling if users do not pass guid values into the parameters. However, the key points regarding getting the data from the URI are illustrated.

It’s also important to design your page logic to carefully handle null or missing values for certain parameters. Your application should be resilient and accommodating to the presence or absence of specific query parameters. This level of flexibility ensures that your Blazor app can deliver a rich, user-centric experience.

Advantages

🏋️ Flexibility: This method allows for optional parameters. The page can gracefully load even if certain parameters are omitted, provided that your page logic is designed to handle such scenarios.

🚀 Complex Data Handling: Suited for passing a variety of data types and multiple values.

🚨 Custom Error Handling Logic: You can handle incorrect query values using your own custom logic and therefore are not reliant on being redirected to a generic error page when a parameter was incorrectly entered.

Disadvantages

🔨 Manual Parameter Setting: The need to parse the query string adds an extra step to data retrieval. There is unfortunately no magic of assigning the parameters.

🔍 Loose Typing: Without strict type enforcement, the data extracted from the query string is a string input and therefore more prone to parse errors.

Conclusion

At this point, you may be left wondering which method to use. Both methods serve their unique purposes in the toolkit of a Blazor Server developer, much like how different chocolate experiences cater to various occasions and preferences.

Parameters in Page Route: Opt for this method when your data needs are clear and defined. It’s perfect for scenarios where you require clean URLs and strong typing, ensuring that each piece of data is precisely where it should be. Use this approach for essential parameters that define the core content of your page, providing a straightforward and secure path to your data.

Query Strings with NavigationManager and QueryHelpers: When your application requires a more flexible approach, allowing users to mix and match their input parameters, query strings come into play. This method is ideal for optional parameters, complex data handling, or when the data might vary widely from one user to another. It’s the assorted chocolate box of data passing methods, where surprises are welcome, and variety is the spice of life.

Remember, the elegance lies in using the right approach for the right situation. Your choice should enhance the experience and delight of the end user.

If you’ve got this far, thank you!

Happy coding, and don’t hesitate to spread the sweetness by commenting and sharing your own experiences! 🧠📈

Further Reading

For those looking to deepen their understanding, dive into the official documentation:

--

--