Пример #1
0
    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());
    }
Пример #4
0
 private IReadOnlyList <Endpoint> CreateConventionalRoutedEndpoints(ActionDescriptor action, ConventionalRouteEntry route)
 {
     return(CreateConventionalRoutedEndpoints(action, new[] { route, }));
 }