Condividi tramite


Abilitare il supporto di ASP.NET Core Blazor Server con Yarp nella migrazione incrementale

Quando si aggiunge Yarp a un'app Blazor Server , entrambi tentano di agire come route di fallback per il routing delle richieste dell'app. O Blazor Yarp gestisce il routing in modo arbitrario, il che significa che gli scenari come il deep linking in Blazor potrebbero non riuscire. Questo problema verrà risolto nella versione .NET 8 di quest'anno. Per la migrazione a ASP.NET Core 6.0 e 7.0, eseguire il mapping Blazordegli endpoint per ottenere il routing corretto delle richieste seguendo le indicazioni riportate in questo articolo.

Aggiungere la classe di estensioni del generatore di route seguente al progetto.

BlazorEndpointRouteBuilderExtensions.cs:

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Routing;

public static class BlazorEndpointRouteBuilderExtensions {
    public static IEndpointConventionBuilder MapBlazorPages(
        this IEndpointRouteBuilder endpoints, string page)
    {
        var assembly = Assembly.GetEntryAssembly();

        if (assembly is null)
        {
            throw new InvalidOperationException("No entry assembly available.");
        }

        return endpoints.MapBlazorPages(page, assembly);
    }

    public static IEndpointConventionBuilder MapBlazorPages(
        this IEndpointRouteBuilder endpoints, string page, 
        params Assembly[] assemblies)
    {
        ArgumentNullException.ThrowIfNull(assemblies);

        var builder = new BlazorEndpointConventionBuilder();

        foreach (var route in GetRoutes(assemblies))
        {
            var conventionBuilder = endpoints.MapFallbackToPage(route, page);

            conventionBuilder.Add(b =>
            {
                b.DisplayName = $"Blazor {route}";
                ((RouteEndpointBuilder)b).Order = -1;
            });

            builder.Add(conventionBuilder);
        }

        return builder;
    }

    private static IEnumerable<string> GetRoutes(Assembly[] assemblies)
    {
        foreach (var assembly in assemblies)
        {
            foreach (var type in assembly.GetTypes())
            {
                if (typeof(IComponent).IsAssignableFrom(type))
                {
                    foreach (var attribute in 
                        type.GetCustomAttributes(typeof(RouteAttribute)))
                    {
                        if (attribute is RouteAttribute { Template: { } route })
                        {
                            yield return route;
                        }
                    }
                }
            }
        }
    }

    private sealed class BlazorEndpointConventionBuilder : IEndpointConventionBuilder {
        private readonly List<IEndpointConventionBuilder> builders = new();

        public void Add(IEndpointConventionBuilder builder)
        {
            builders.Add(builder);
        }

        void IEndpointConventionBuilder.Add(Action<EndpointBuilder> convention)
        {
            foreach (var builder in builders)
            {
                builder.Add(convention);
            }
        }

#if NET7_0_OR_GREATER
        void IEndpointConventionBuilder.Finally(
            Action<EndpointBuilder> finalConvention)
        {
            foreach (var builder in builders)
            {
                builder.Finally(finalConvention);
            }
        }
#endif
    }
}

Nel codice precedente:

  • Il valore predefinito di EndpointBuilder.DisplayName è Fallback {route}. La riga che la modifica in Blazor {route} (b.DisplayName = $"Blazor {route}";) identifica la Blazor route come registrata in modo esplicito.
  • Per la riga che imposta l'ordine di route (((RouteEndpointBuilder)b).Order = -1;), {page} ha un ordine di route di 0 per impostazione predefinita. L'impostazione dell'ordine Blazor di route su -1 garantisce che l'ordine venga modificato in modo da assegnare la precedenza alla Blazor route.

Aggiornare la registrazione dell'app per l'uso Blazor in Program.cs:

- app.MapFallbackToPage("/_Host");
+ app.MapBlazorPages("/_Host");

A questo punto, l'app deve instradare correttamente le richieste per Blazor e Yarp, incluso il deep linking alle pagine.