Share via


Activer la prise en charge ASP.NET Core Blazor Server avec Yarp dans la migration incrémentielle

Lors de l’ajout de Yarp à une Blazor Server application, les deux tentent d’agir comme routes de secours pour le routage des requêtes de l’application. Soit Blazor soit Yarp gère le routage de manière arbitraire, ce qui signifie que des scénarios tels que l'insertion de liens Blazor peuvent échouer. Ce problème sera résolu dans la version .NET 8 plus tard cette année. Pour la migration vers ASP.NET Core 6.0 et 7.0, mappez les points de terminaison Blazor pour obtenir un routage correct des requêtes en suivant les instructions de cet article.

Ajoutez la classe d'extension de constructeur de routes suivante au projet.

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
    }
}

Dans le code précédent :

  • EndpointBuilder.DisplayName a la valeur par défaut Fallback {route}. La ligne qui le remplace par Blazor {route} (b.DisplayName = $"Blazor {route}";) identifie Blazor la route comme étant explicitement enregistré.
  • Pour la ligne qui définit l’ordre d’itinéraire (((RouteEndpointBuilder)b).Order = -1;), {page} a un ordre d’itinéraire de 0 par défaut. La définition de l’ordre Blazor de routage -1 garantit que l’ordre est modifié pour donner la priorité à l’itinéraire Blazor .

Mettre à jour l'enregistrement de l'application pour utiliser Blazor dans Program.cs :

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

À ce stade, l'application devrait acheminer correctement les demandes pour Blazor et Yarp, y compris les liens profonds vers les pages.