次の方法で共有


増分移行で Yarp を使用して ASP.NET Core Blazor Server サポートを有効にする

Yarp を Blazor Server アプリに追加する場合、両方ともアプリの要求ルーティングのフォールバック ルートとして機能しようとします。 Blazor または Yarp が任意でルーティングを処理します。これは、Blazor のディープ リンクなどのシナリオが失敗する可能性があることを意味します。 これは、今年後半の .NET 8 リリースで修正される予定です。 ASP.NET Core 6.0 および 7.0 への移行の場合は、この記事のガイダンスに従って、正しい要求ルーティングを実現するように Blazor のエンドポイントをマップします。

次のルート ビルダー拡張機能クラスをプロジェクトに追加します。

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

上のコードでは以下の操作が行われます。

  • EndpointBuilder.DisplayName の既定値は Fallback {route} です。 これを Blazor {route} (b.DisplayName = $"Blazor {route}";) に変更する行は、Blazor ルートを明示的に登録済みとして識別します。
  • ルート順序 (((RouteEndpointBuilder)b).Order = -1;) を設定する行の場合、既定では {page}0 のルート順序があります。 Blazor ルートの順序を -1 に設定すると、Blazor ルートの優先順位を指定するように順序が変更されます。

Program.cs で Blazor を使用するためのアプリの登録を更新します。

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

この時点で、アプリは、ページに対するディープ リンクを含め、Blazor と Yarp に対して要求を正しくルーティングする必要があります。