File: Builder\RazorComponentsEndpointHttpContextExtensions.cs
Web Access
Project: src\src\Components\Endpoints\src\Microsoft.AspNetCore.Components.Endpoints.csproj (Microsoft.AspNetCore.Components.Endpoints)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Concurrent;
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.AspNetCore.Components.Endpoints;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Http;
 
[assembly: MetadataUpdateHandler(typeof(RazorComponentsEndpointHttpContextExtensions.MetadataUpdateHandler))]
 
namespace Microsoft.AspNetCore.Components.Routing;
 
/// <summary>
/// Extensions to <see cref="HttpContext"/> for Razor component applications.
/// </summary>
public static class RazorComponentsEndpointHttpContextExtensions
{
    private static readonly ConcurrentDictionary<Type, bool> AcceptsInteractiveRoutingCache = new();
 
    /// <summary>
    /// Determines whether the current endpoint is a Razor component that can be reached through
    /// interactive routing. This is true for all page components except if they declare the
    /// attribute <see cref="ExcludeFromInteractiveRoutingAttribute"/>.
    /// </summary>
    /// <param name="context">The <see cref="HttpContext"/>.</param>
    /// <returns>True if the current endpoint is a Razor component that does not declare <see cref="ExcludeFromInteractiveRoutingAttribute"/>.</returns>
    public static bool AcceptsInteractiveRouting(this HttpContext context)
    {
        ArgumentNullException.ThrowIfNull(context);
 
        var pageType = context.GetEndpoint()?.Metadata.GetMetadata<ComponentTypeMetadata>()?.Type;
 
        return pageType is not null
            && AcceptsInteractiveRoutingCache.GetOrAdd(
                pageType,
                static pageType => !pageType.IsDefined(typeof(ExcludeFromInteractiveRoutingAttribute)));
    }
 
    internal static class MetadataUpdateHandler
    {
        /// <summary>
        /// Invoked as part of <see cref="MetadataUpdateHandlerAttribute" /> contract for hot reload.
        /// </summary>
        public static void ClearCache(Type[]? _)
            => AcceptsInteractiveRoutingCache.Clear();
    }
}