This library lets you build single‑URL, multi‑page Blazor apps by routing between components without changing the browser address or exposing URL parameters. It also persists navigation state and helps prevent URL tampering and hijacking.
https://danielmendie.github.io/PageFlow.Blazor/
- Blazor Server
- Blazor WebAssembly
- MAUI Blazor Hybrid
- Static URL - Navigate between pages while the browser URL stays the same.
- Page Retention - Restore the last visited page after refresh or browser reopen.
- Previous Page History - Navigate back through previously visited dynamic pages.
- Nav Menu Binding - Trigger navigation from any menu/button via attributes.
- Multi-App Switching - Partition routes into logical “apps” using
appId. - Storage Option - Persist navigation state via LocalStorage
- CLI Tool - Generate and build route metadata from your project automatically.
To begin, install the latest version of PageFlow.Blazor Nuget package from Visual Studio or use the Command-line tool:
dotnet add package PageFlow.Blazor
Open your project's Program.cs file and add this section
builder.Services.AddBlazorPageFlow();To prevent the app from remembering last visited page, set option IgnoreRouteHistory to True
STEPS HIGHLIGHTED HERE CAN BE DONE AUTOMATICALLY USING THE CLI TOOL
- Create a base class in the root directory and inherit the
BlazorPageFlowBaseclass then add thePageFlowBaseComponentattribute to your base component class. Your class should look similar to this:
using PageFlow.Blazor;
using Microsoft.AspNetCore.Components;
namespace Test.Pages;
[PageFlowBaseComponent]
public class MyBaseComponent : BlazorPageFlowBase
{
}The PageFlowBaseComponent attribute should be specified on the custom class acting as your component base class This is very important
- Open the
_Imports.razorfile and add the following lines of code
@using PageFlow.Blazor
@inherits MyBaseComponentMyBaseComponent - This should be the name of your base component class(however you had called it)
-
Add the FlowUI component to the Home.razor or Index.razor file
<PageFlow.Blazor.FlowUI /> -
In the Home.razor or Index.razor override OnInitializedAsync() and call the OnAppNavigationSetup(). You only have to add this call once.
protected override async Task OnInitializedAsync()
{
await OnAppFlowSetup();
}The PageFlow.Blazor is used for configuring your project. You'll use class and property attributes to define your routable components and parameter properties.
To define a routable component, decorate it with the PageFlowRoutableComponent attribute. Here's a typical example
using PageFlow.Blazor;
using Microsoft.AspNetCore.Components;
namespace TestApp.Pages
{
[PageFlowRoutableComponent(pageName: "Sample", isDefault: true)]
public partial class Sample
{
[Parameter] public string Username { get; set; } = null!;
}
}PageFlowRoutableComponent - This attribute requires three parameters; pageName(string: name of the page), isDefault(bool: indicates if the component is the default route for the app Id), appId - optional(int: used to categorize your app into different sub apps)
To navigate to the sample page you call NavigateToAsync and pass the component name and its parameters if any
await NavigateToAsync(nameof(Sample), new Dictionary<string, string> { { "Username", "Daniel Mendie" } });Once your routable components are decorated. The rest is up to PageFlow.Blazor.CLI tool to complete😉
Command line tool for generating page routes for the dynamic navigation use in your application
To install the latest version of PageFlow.Blazor.CLI tool, run dotnet tool install -g PageFlow.Blazor.CLI from command line
The CLI is responsible for generating route pages and binding them. To use it, open command-line tool to the directory of your project to run the following commands:
- To generate route pages
pageflow routes generate
Other additional command flags include:
Point to a different project path using -p or --path
pageflow routes generate --path path\to\your\projet\directory
Force build project before generating routes using -f or --force
pageflow routes generate --force
Verbose logging using -v or --verbose
pageflow routes generate --verbose
Once the command runs successfully, your BaseNavigator class will be populated with the routes.
Now run the project, and don't forget to check your browser's dev tool console for extra log information if you ever get into an issue
Here are a couple of extra things you can do to make this package serve your business needs adequately. The following methods can be overridden based on your needs and logic
OnAfterNavigateAsync - Event triggered after a successful page navigation
Scenario: You want to persist user page session across multiple devices, get route metadata and send to your backend api
protected override Task OnAfterNavigateAsync(RoutePageInfo route, Dictionary<string, string>? parameters)
{
return base.OnAfterNavigateAsync(route, parameters);
}OnBeforeNavigateAsync - Event triggered before a page navigation
Scenario: You want to do a pre-conditional check for feature accessibility or permission
protected override Task OnBeforeNavigateAsync(RoutePageInfo route, Dictionary<string, string>? parameters)
{
return base.OnBeforeNavigateAsync(route, parameters);
}OnNavigationFailedAsync - Event triggered when page navigation fails
protected override Task OnNavigationFailedAsync(Exception exception)
{
return base.OnNavigationFailedAsync(exception);
}OnCannotGoBackAsync - Event triggered when there is no page in history to return to
protected override Task OnCannotGoBackAsync()
{
return base.OnCannotGoBackAsync();
}RestoreOrNavigateToDefaultAsync - Entry point for dynamic navigation to either restore from history or find default page based on generated pages
Scenario: Fetch previous route metadata from API(multiple devices) then restore page from the fetched data
protected override Task RestoreOrNavigateToDefaultAsync()
{
return base.RestoreOrNavigateToDefaultAsync();
}Cheers!
Contributions are welcome! Please see CONTRIBUTING for guidelines on setting up your environment, coding style, and making pull requests.
This project is licensed under the MIT License. See LICENSE for details.