protected override List <Endpoint> CreateEndpoints( RoutePattern?groupPrefix, IReadOnlyList <ActionDescriptor> actions, IReadOnlyList <Action <EndpointBuilder> > conventions, IReadOnlyList <Action <EndpointBuilder> > groupConventions) { 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>(), groupConventions: groupConventions, conventions: conventions, CreateInertEndpoints, groupPrefix); } } return(endpoints); }
private async Task <CompiledPageActionDescriptor> LoadAsyncCore(PageActionDescriptor actionDescriptor, EndpointMetadataCollection endpointMetadata) { var viewDescriptor = await Compiler.CompileAsync(actionDescriptor.RelativePath); var context = new PageApplicationModelProviderContext(actionDescriptor, viewDescriptor.Type.GetTypeInfo()); for (var i = 0; i < _applicationModelProviders.Length; i++) { _applicationModelProviders[i].OnProvidersExecuting(context); } for (var i = _applicationModelProviders.Length - 1; i >= 0; i--) { _applicationModelProviders[i].OnProvidersExecuted(context); } ApplyConventions(_conventions, context.PageApplicationModel); var compiled = CompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel, _globalFilters); // We need to create an endpoint for routing to use and attach it to the CompiledPageActionDescriptor... // routing for pages is two-phase. First we perform routing using the route info - we can do this without // compiling/loading the page. Then once we have a match we load the page and we can create an endpoint // with all of the information we get from the compiled action descriptor. var endpoints = new List <Endpoint>(); _endpointFactory.AddEndpoints( endpoints, routeNames: new HashSet <string>(StringComparer.OrdinalIgnoreCase), action: compiled, routes: Array.Empty <ConventionalRouteEntry>(), conventions: new Action <EndpointBuilder>[] { b => { // Metadata from PageActionDescriptor is less significant than the one discovered from the compiled type. // Consequently, we'll insert it at the beginning. for (var i = endpointMetadata.Count - 1; i >= 0; i--) { b.Metadata.Insert(0, endpointMetadata[i]); } }, }, createInertEndpoints: false); // In some test scenarios there's no route so the endpoint isn't created. This is fine because // it won't happen for real. compiled.Endpoint = endpoints.SingleOrDefault(); return(compiled); }
protected override List <Endpoint> CreateEndpoints(IReadOnlyList <ActionDescriptor> actions, IReadOnlyList <Action <EndpointBuilder> > conventions) { var endpoints = new List <Endpoint>(); for (var i = 0; i < actions.Count; i++) { if (actions[i] is PageActionDescriptor action) { _endpointFactory.AddEndpoints(endpoints, action, Array.Empty <ConventionalRouteEntry>(), conventions); } } return(endpoints); }
protected override List <Endpoint> CreateEndpoints(IReadOnlyList <ActionDescriptor> actions, IReadOnlyList <Action <EndpointBuilder> > conventions) { var endpoints = new List <Endpoint>(); var keys = new HashSet <string>(StringComparer.OrdinalIgnoreCase); // MVC guarantees that when two of it's endpoints have the same route name they are equivalent. // // However, Endpoint Routing requires Endpoint Names to be unique. var routeNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); // For each controller action - add the relevant endpoints. // // 1. If the action is attribute routed, we use that information verbatim // 2. If the action is conventional routed // a. Create a *matching only* endpoint for each action X route (if possible) // b. Ignore link generation for now for (var i = 0; i < actions.Count; i++) { if (actions[i] is ControllerActionDescriptor action) { _endpointFactory.AddEndpoints(endpoints, routeNames, action, _routes, conventions, CreateInertEndpoints); if (_routes.Count > 0) { // If we have conventional routes, keep track of the keys so we can create // the link generation routes later. foreach (var kvp in action.RouteValues) { keys.Add(kvp.Key); } } } } // Now create a *link generation only* endpoint for each route. This gives us a very // compatible experience to previous versions. for (var i = 0; i < _routes.Count; i++) { var route = _routes[i]; _endpointFactory.AddConventionalLinkGenerationRoute(endpoints, routeNames, keys, route, conventions); } return(endpoints); }
public CompiledPageActionDescriptor Load(PageActionDescriptor actionDescriptor) { if (actionDescriptor == null) { throw new ArgumentNullException(nameof(actionDescriptor)); } var compileTask = Compiler.CompileAsync(actionDescriptor.RelativePath); var viewDescriptor = compileTask.GetAwaiter().GetResult(); var context = new PageApplicationModelProviderContext(actionDescriptor, viewDescriptor.Type.GetTypeInfo()); for (var i = 0; i < _applicationModelProviders.Length; i++) { _applicationModelProviders[i].OnProvidersExecuting(context); } for (var i = _applicationModelProviders.Length - 1; i >= 0; i--) { _applicationModelProviders[i].OnProvidersExecuted(context); } ApplyConventions(_conventions, context.PageApplicationModel); var compiled = CompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel, _globalFilters); // We need to create an endpoint for routing to use and attach it to the CompiledPageActionDescriptor... // routing for pages is two-phase. First we perform routing using the route info - we can do this without // compiling/loading the page. Then once we have a match we load the page and we can create an endpoint // with all of the information we get from the compiled action descriptor. var endpoints = new List <Endpoint>(); _endpointFactory.AddEndpoints(endpoints, compiled, Array.Empty <ConventionalRouteEntry>(), Array.Empty <Action <EndpointBuilder> >()); // In some test scenarios there's no route so the endpoint isn't created. This is fine because // it won't happen for real. compiled.Endpoint = endpoints.SingleOrDefault(); return(compiled); }
private async Task <CompiledPageActionDescriptor> LoadAsyncCore(PageActionDescriptor actionDescriptor, EndpointMetadataCollection endpointMetadata) { var viewDescriptor = await Compiler.CompileAsync(actionDescriptor.RelativePath); var compiled = _compiledPageActionDescriptorFactory.CreateCompiledDescriptor(actionDescriptor, viewDescriptor); var endpoints = new List <Endpoint>(); _endpointFactory.AddEndpoints( endpoints, routeNames: new HashSet <string>(StringComparer.OrdinalIgnoreCase), action: compiled, routes: Array.Empty <ConventionalRouteEntry>(), groupConventions: Array.Empty <Action <EndpointBuilder> >(), conventions: new Action <EndpointBuilder>[] { b => { // Copy Endpoint metadata for PageActionActionDescriptor to the compiled one. // This is particularly important for the runtime compiled scenario where endpoint metadata is added // to the PageActionDescriptor, which needs to be accounted for when constructing the // CompiledPageActionDescriptor as part of the one of the many matcher policies. // Metadata from PageActionDescriptor is less significant than the one discovered from the compiled type. // Consequently, we'll insert it at the beginning. for (var i = endpointMetadata.Count - 1; i >= 0; i--) { b.Metadata.Insert(0, endpointMetadata[i]); } }, }, createInertEndpoints: false); // In some test scenarios there's no route so the endpoint isn't created. This is fine because // it won't happen for real. compiled.Endpoint = endpoints.SingleOrDefault(); return(compiled); }
public void RequestDelegateFactoryWorks() { // Arrange var values = new { controller = "TestController", action = "TestAction", page = (string)null }; var action = CreateActionDescriptor(values, "{controller}/{action}/{page}"); action.AttributeRouteInfo.Name = "Test"; RequestDelegate del = context => Task.CompletedTask; var requestDelegateFactory = new Mock <IRequestDelegateFactory>(); requestDelegateFactory.Setup(m => m.CreateRequestDelegate(action, It.IsAny <RouteValueDictionary>())).Returns(del); // Act var factory = new ActionEndpointFactory(Services.GetRequiredService <RoutePatternTransformer>(), new[] { requestDelegateFactory.Object }); var endpoints = new List <Endpoint>(); factory.AddEndpoints(endpoints, new HashSet <string>(), action, Array.Empty <ConventionalRouteEntry>(), Array.Empty <Action <EndpointBuilder> >(), createInertEndpoints: false); var endpoint = Assert.IsType <RouteEndpoint>(Assert.Single(endpoints)); // Assert Assert.Same(del, endpoint.RequestDelegate); }