blazor-navigation-manager

NavigationManager: navegación programática y query strings

  • 4 min

NavigationManager es el servicio de Blazor que representa la URI actual y permite iniciar o supervisar la navegación.

En el artículo anterior definimos rutas con @page. Ahora necesitamos navegar desde C# en casos como estos:

  • El usuario rellena un formulario y, al guardar, queremos redirigirlo al listado.
  • El usuario hace login y queremos enviarlo al Panel de Control.
  • Ocurre un error y queremos forzar una recarga de la página.

Para todo esto, Blazor nos proporciona un servicio inyectable fundamental: el NavigationManager.

Inyectar el servicio

Al ser un servicio del núcleo de ASP.NET Core, ya está registrado en el contenedor de inyección de dependencias. Solo tenemos que pedirlo.

En un archivo .razor:

@inject NavigationManager NavManager
Copied!

En una clase .razor.cs (Code-Behind):

[Inject]
public NavigationManager NavManager { get; set; } = default!;
Copied!

El método principal es NavigateTo. Recibe una URI relativa o absoluta y, cuando el destino interno admite navegación mejorada o interactiva, evita una recarga completa.

private void IrAlInicio()
{
    // Navegación relativa (recomendada)
    NavManager.NavigateTo("/");

    // Navegación a otra página interna
    NavManager.NavigateTo("/productos/detalles/5");
}
Copied!

Opciones avanzadas de navegación

NavigateTo también acepta un objeto NavigationOptions para controlar la transición.

ForceLoad: forzar una recarga

A veces necesitamos “reiniciar” la aplicación, por ejemplo, si el usuario ha cerrado sesión y queremos limpiar completamente la memoria del navegador, o si estamos navegando a una página externa fuera de nuestra SPA.

// Esto provoca un F5 (refresco completo) en el navegador
NavManager.NavigateTo("/login", forceLoad: true);
Copied!

ReplaceHistoryEntry: reemplazar el historial

Imagina un flujo de Login.

  1. Usuario entra en /login.
  2. Se loguea correctamente.
  3. Lo redirigimos a /dashboard.

Si el usuario pulsa «Atrás», volverá al login. Para evitarlo, ReplaceHistoryEntry sustituye la entrada actual del historial en lugar de añadir otra.

NavManager.NavigateTo("/dashboard", new NavigationOptions
{
    ReplaceHistoryEntry = true
});
Copied!

Construcción de query strings

En el artículo anterior vimos cómo leer parámetros de la URL ([SupplyParameterFromQuery]). Ahora veremos cómo escribirlos.

Podríamos concatenar cadenas manualmente: NavManager.NavigateTo($"/buscar?q={texto}&page={pagina}");

Esta concatenación es peligrosa (¿qué ocurre si texto contiene espacios o caracteres especiales?). En Blazor moderno podemos usar el método GetUriWithQueryParameters.

private void FiltrarProductos()
{
    // 1. Preparamos los parámetros en un diccionario
    var parametros = new Dictionary<string, object?>
    {
        { "categoria", "electronica" },
        { "stock", true },
        { "orden", "precio_desc" },
        { "pagina", 1 }
    };

    // 2. Generamos la URL segura
    // Resultado: /productos?categoria=electronica&stock=true&orden=precio_desc&pagina=1
    var url = NavManager.GetUriWithQueryParameters("/productos", parametros);

    // 3. Navegamos
    NavManager.NavigateTo(url);
}
Copied!

Este método se encarga automáticamente de codificar los caracteres (URL Encoding) y manejar los nulos.

Leer la URL actual

A veces necesitamos saber “dónde estamos” para tomar decisiones lógicas (por ejemplo, mostrar un botón solo si estamos en la Home).

  • NavManager.Uri: Devuelve la URL completa absoluta (ej: https://localhost:5001/productos?id=5).
  • NavManager.BaseUri: Devuelve la raíz del sitio (ej: https://localhost:5001/).

Para obtener la ruta relativa (lo que solemos necesitar), podemos usar ToBaseRelativePath:

var absoluta = NavManager.Uri; // https://misitio.com/admin/usuarios
var relativa = NavManager.ToBaseRelativePath(absoluta); // admin/usuarios
Copied!

Escuchar eventos de navegación

El NavigationManager no solo sirve para actuar, también para reaccionar. Podemos suscribirnos al evento LocationChanged para saber cuándo el usuario ha cambiado de página.

Esto es muy útil para sistemas de Analytics, logging o para cerrar menús desplegables al cambiar de ruta.

@implements IDisposable
@inject NavigationManager NavManager

<p>Estás en: @currentUrl</p>

@code {
    private string currentUrl = string.Empty;

    protected override void OnInitialized()
    {
        currentUrl = NavManager.Uri;

        // Nos suscribimos al evento
        NavManager.LocationChanged += OnLocationChanged;
    }

    private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
    {
        currentUrl = e.Location;
        Console.WriteLine($"El usuario ha navegado a: {e.Location}");

        // Importante: StateHasChanged es necesario aquí porque el evento
        // puede dispararse fuera del ciclo de vida normal de renderizado de este componente.
        _ = InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        // Nos desuscribimos para que el servicio no retenga el componente
        NavManager.LocationChanged -= OnLocationChanged;
    }
}
Copied!

Si te suscribes a LocationChanged y no te desuscribes en el Dispose, tu componente seguirá “vivo” en memoria aunque el usuario cambie de página, consumiendo recursos y pudiendo lanzar errores.