Skip to content

Routing

Termina uses ASP.NET-style route templates for navigation between pages.

Route Registration

Register routes when configuring Termina:

csharp
builder.Services.AddTermina("/", termina =>
{
    // Simple routes
    termina.RegisterRoute<HomePage, HomeViewModel>("/");
    termina.RegisterRoute<AboutPage, AboutViewModel>("/about");

    // Route with parameters
    termina.RegisterRoute<DetailPage, DetailViewModel>("/items/{id}");
    termina.RegisterRoute<UserPage, UserViewModel>("/users/{name}");
});

Route Parameters

Basic Parameters

Capture path segments as parameters:

csharp
// Route: "/items/{id}"
// Matches: "/items/42", "/items/abc"
termina.RegisterRoute<DetailPage, DetailViewModel>("/items/{id}");

Typed Parameters

Constrain parameters to specific types:

csharp
// Only matches integers
termina.RegisterRoute<DetailPage, DetailViewModel>("/items/{id:int}");
// Matches: "/items/42"
// Doesn't match: "/items/abc"

// Only matches GUIDs
termina.RegisterRoute<DetailPage, DetailViewModel>("/items/{id:guid}");

Supported Type Constraints

ConstraintPatternExample Match
int{id:int}42, -1
bool{flag:bool}true, false
guid{id:guid}550e8400-e29b-...
(none){name}Any string

Receiving Parameters

Using [FromRoute]

The simplest approach - use source generation:

csharp
public partial class DetailViewModel : ReactiveViewModel
{
    [FromRoute] private int _id;

    public override void OnActivated()
    {
        // Id is already populated
        LoadItem(Id);
    }
}

Manual Parameter Access

Access raw parameters via the route context:

csharp
public class DetailViewModel : ReactiveViewModel
{
    public int Id { get; private set; }

    internal void ApplyRouteParameters(IDictionary<string, object> parameters)
    {
        if (parameters.TryGetValue("id", out var value))
        {
            Id = Convert.ToInt32(value);
        }
    }
}

Initial Route

The first argument to AddTermina is the starting route:

csharp
// Start at home page
builder.Services.AddTermina("/", termina => { ... });

// Start at specific page
builder.Services.AddTermina("/dashboard", termina => { ... });

Route Matching

Routes are matched in registration order. The first match wins:

csharp
// More specific routes should come first
termina.RegisterRoute<SpecificPage, SpecificViewModel>("/items/special");
termina.RegisterRoute<DetailPage, DetailViewModel>("/items/{id}");
termina.RegisterRoute<ListPage, ListViewModel>("/items");

Simple Path

csharp
Navigate("/items/42");

Template with Values

csharp
NavigateWithParams("/items/{id}", new { id = 42 });
NavigateWithParams("/users/{name}", new { name = "alice" });

Route Source Code

View RouteTemplate implementation
csharp
namespace Termina.Routing;

/// <summary>
/// A parsed route template consisting of segments.
/// </summary>
/// <remarks>
/// Examples:
/// <list type="bullet">
///   <item>"/tasks" → one literal segment</item>
///   <item>"/tasks/{id}" → two segments: literal "tasks", parameter "id"</item>
///   <item>"/tasks/{id:int}" → two segments: literal "tasks", parameter "id" with int constraint</item>
/// </list>
/// </remarks>
public sealed class RouteTemplate
{
    /// <summary>
    /// The original template string.
    /// </summary>
    public string Template { get; }

    /// <summary>
    /// The parsed segments of the route.
    /// </summary>
    public IReadOnlyList<RouteSegment> Segments { get; }

    /// <summary>
    /// Gets the parameter names defined in this template.
    /// </summary>
    public IReadOnlyList<string> ParameterNames { get; }

    internal RouteTemplate(string template, IReadOnlyList<RouteSegment> segments)
    {
        Template = template;
        Segments = segments;
        ParameterNames = segments
            .Where(s => s.IsParameter)
            .Select(s => s.Value)
            .ToList();
    }

    /// <summary>
    /// Gets whether this template has any parameters.
    /// </summary>
    public bool HasParameters => ParameterNames.Count > 0;

    public override string ToString() => Template;
}

Released under the Apache 2.0 License.