private RouteEndpoint CreateConventionalRoutedEndpoint(ActionDescriptor action, ConventionalRouteEntry route) { Assert.NotNull(action.RouteValues); var endpoints = new List <Endpoint>(); Factory.AddEndpoints(endpoints, new HashSet <string>(), action, new[] { route, }, Array.Empty <Action <EndpointBuilder> >(), createInertEndpoints: false); var endpoint = Assert.IsType <RouteEndpoint>(Assert.Single(endpoints)); // This should be true for all conventional-routed actions. AssertIsSubset(new RouteValueDictionary(action.RouteValues), endpoint.RoutePattern.RequiredValues); return(endpoint); }
/// <summary> /// Adds MVC to the <see cref="IApplicationBuilder"/> request execution pipeline. /// </summary> /// <param name="app">The <see cref="IApplicationBuilder"/>.</param> /// <param name="configureRoutes">A callback to configure MVC routes.</param> /// <returns>A reference to this instance after the operation has completed.</returns> public static IApplicationBuilder UseMvc( this IApplicationBuilder app, Action <IRouteBuilder> configureRoutes) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (configureRoutes == null) { throw new ArgumentNullException(nameof(configureRoutes)); } VerifyMvcIsRegistered(app); var options = app.ApplicationServices.GetRequiredService <IOptions <MvcOptions> >(); if (options.Value.EnableEndpointRouting) { var dataSource = app.ApplicationServices.GetRequiredService <ActionEndpointDataSource>(); var endpointRouteBuilder = new EndpointRouteBuilder(app); configureRoutes(endpointRouteBuilder); foreach (var router in endpointRouteBuilder.Routes) { // Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint // Sub-types could have additional customization that we can't knowingly convert if (router is Route route && router.GetType() == typeof(Route)) { var entry = new ConventionalRouteEntry( route.Name, route.RouteTemplate, route.Defaults, route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value), route.DataTokens); dataSource.AddRoute(entry); } else { throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing."); } }
public void AddConventionalLinkGenerationRoute( List <Endpoint> endpoints, HashSet <string> routeNames, HashSet <string> keys, ConventionalRouteEntry route, IReadOnlyList <Action <EndpointBuilder> > conventions) { if (endpoints == null) { throw new ArgumentNullException(nameof(endpoints)); } if (keys == null) { throw new ArgumentNullException(nameof(keys)); } if (conventions == null) { throw new ArgumentNullException(nameof(conventions)); } var requiredValues = new RouteValueDictionary(); foreach (var key in keys) { if (route.Pattern.GetParameter(key) != null) { // Parameter (allow any) requiredValues[key] = RoutePattern.RequiredValueAny; } else if (route.Pattern.Defaults.TryGetValue(key, out var value)) { requiredValues[key] = value; } else { requiredValues[key] = null; } } // We have to do some massaging of the pattern to try and get the // required values to be correct. var pattern = _routePatternTransformer.SubstituteRequiredValues(route.Pattern, requiredValues); if (pattern == null) { // We don't expect this to happen, but we want to know if it does because it will help diagnose the bug. throw new InvalidOperationException("Failed to create a conventional route for pattern: " + route.Pattern); } var builder = new RouteEndpointBuilder(context => Task.CompletedTask, pattern, route.Order) { DisplayName = "Route: " + route.Pattern.RawText, Metadata = { new SuppressMatchingMetadata(), }, }; if (route.RouteName != null) { builder.Metadata.Add(new RouteNameMetadata(route.RouteName)); } // See comments on the other usage of EndpointNameMetadata in this class. // // The set of cases for a conventional route are much simpler. We don't need to check // for Endpoint Name already exising here because there's no way to add an attribute to // a conventional route. if (route.RouteName != null && routeNames.Add(route.RouteName)) { builder.Metadata.Add(new EndpointNameMetadata(route.RouteName)); } for (var i = 0; i < conventions.Count; i++) { conventions[i](builder); } for (var i = 0; i < route.Conventions.Count; i++) { route.Conventions[i](builder); } endpoints.Add((RouteEndpoint)builder.Build()); }
private IReadOnlyList <Endpoint> CreateConventionalRoutedEndpoints(ActionDescriptor action, ConventionalRouteEntry route) { return(CreateConventionalRoutedEndpoints(action, new[] { route, })); }