| File: Infrastructure\PageActionEndpointDataSource.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.RazorPages\src\Microsoft.AspNetCore.Mvc.RazorPages.csproj (Microsoft.AspNetCore.Mvc.RazorPages) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; internal sealed class PageActionEndpointDataSource : ActionEndpointDataSourceBase { private readonly ActionEndpointFactory _endpointFactory; private readonly OrderedEndpointsSequenceProvider _orderSequence; public PageActionEndpointDataSource( PageActionEndpointDataSourceIdProvider dataSourceIdProvider, IActionDescriptorCollectionProvider actions, ActionEndpointFactory endpointFactory, OrderedEndpointsSequenceProvider orderedEndpoints) : base(actions) { DataSourceId = dataSourceIdProvider.CreateId(); _endpointFactory = endpointFactory; _orderSequence = orderedEndpoints; DefaultBuilder = new PageActionEndpointConventionBuilder(Lock, Conventions, FinallyConventions); // IMPORTANT: this needs to be the last thing we do in the constructor. // Change notifications can happen immediately! Subscribe(); } public int DataSourceId { get; } public PageActionEndpointConventionBuilder DefaultBuilder { get; } // Used to control whether we create 'inert' (non-routable) endpoints for use in dynamic // selection. Set to true by builder methods that do dynamic/fallback selection. public bool CreateInertEndpoints { get; set; } protected override List<Endpoint> CreateEndpoints( RoutePattern? groupPrefix, IReadOnlyList<ActionDescriptor> actions, IReadOnlyList<Action<EndpointBuilder>> conventions, IReadOnlyList<Action<EndpointBuilder>> groupConventions, IReadOnlyList<Action<EndpointBuilder>> finallyConventions, IReadOnlyList<Action<EndpointBuilder>> groupFinallyConventions) { var endpoints = new List<Endpoint>(); var routeNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); for (var i = 0; i < actions.Count; i++) { if (actions[i] is PageActionDescriptor action) { _endpointFactory.AddEndpoints(endpoints, routeNames, action, Array.Empty<ConventionalRouteEntry>(), conventions: conventions, groupConventions: groupConventions, finallyConventions: finallyConventions, groupFinallyConventions: groupFinallyConventions, CreateInertEndpoints, groupPrefix); } } return endpoints; } internal void AddDynamicPageEndpoint(IEndpointRouteBuilder endpoints, string pattern, Type transformerType, object? state, int? order = null) { CreateInertEndpoints = true; lock (Lock) { order ??= _orderSequence.GetNext(); endpoints.Map( pattern, context => { throw new InvalidOperationException("This endpoint is not expected to be executed directly."); }) .Add(b => { ((RouteEndpointBuilder)b).Order = order.Value; b.Metadata.Add(new DynamicPageRouteValueTransformerMetadata(transformerType, state)); b.Metadata.Add(new PageEndpointDataSourceIdMetadata(DataSourceId)); }); } } }