예제 #1
0
        public RoutingBenchmark()
        {
            var handler = new RouteHandler((next) => Task.FromResult <object>(null));

            var treeBuilder = new TreeRouteBuilder(
                NullLoggerFactory.Instance,
                new RoutePatternBinderFactory(UrlEncoder.Default, new DefaultObjectPoolProvider()),
                new DefaultInlineConstraintResolver(Options.Create(new RouteOptions())));

            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets/{id}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets/search/{term}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("admin/users/{id}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("admin/users/{id}/manage"), "default", 0);

            _treeRouter = treeBuilder.Build();

            _requests = new RequestEntry[NumberOfRequestTypes];

            _requests[0].HttpContext = new DefaultHttpContext();
            _requests[0].HttpContext.Request.Path = "/api/Widgets/5";
            _requests[0].IsMatch = true;
            _requests[0].Values  = new RouteValueDictionary(new { id = 5 });

            _requests[1].HttpContext = new DefaultHttpContext();
            _requests[1].HttpContext.Request.Path = "/admin/users/17/mAnage";
            _requests[1].IsMatch = true;
            _requests[1].Values  = new RouteValueDictionary(new { id = 17 });

            _requests[2].HttpContext = new DefaultHttpContext();
            _requests[2].HttpContext.Request.Path = "/api/Widgets/search/dldldldldld/ddld";
            _requests[2].IsMatch = false;
            _requests[2].Values  = new RouteValueDictionary();
        }
예제 #2
0
        public RoutingBenchmark()
        {
            var handler = new RouteHandler((next) => Task.FromResult <object>(null));

            var treeBuilder = new TreeRouteBuilder(
                NullLoggerFactory.Instance,
                new DefaultObjectPool <UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
                new DefaultInlineConstraintResolver(new OptionsManager <RouteOptions>(new OptionsFactory <RouteOptions>(Enumerable.Empty <IConfigureOptions <RouteOptions> >(), Enumerable.Empty <IPostConfigureOptions <RouteOptions> >()))));

            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets/{id}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("api/Widgets/search/{term}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("admin/users/{id}"), "default", 0);
            treeBuilder.MapInbound(handler, TemplateParser.Parse("admin/users/{id}/manage"), "default", 0);

            _treeRouter = treeBuilder.Build();

            _requests = new RequestEntry[NumberOfRequestTypes];

            _requests[0].HttpContext = new DefaultHttpContext();
            _requests[0].HttpContext.Request.Path = "/api/Widgets/5";
            _requests[0].IsMatch = true;
            _requests[0].Values  = new RouteValueDictionary(new { id = 5 });

            _requests[1].HttpContext = new DefaultHttpContext();
            _requests[1].HttpContext.Request.Path = "/admin/users/17/mAnage";
            _requests[1].IsMatch = true;
            _requests[1].Values  = new RouteValueDictionary(new { id = 17 });

            _requests[2].HttpContext = new DefaultHttpContext();
            _requests[2].HttpContext.Request.Path = "/api/Widgets/search/dldldldldld/ddld";
            _requests[2].IsMatch = false;
            _requests[2].Values  = new RouteValueDictionary();
        }
예제 #3
0
    // internal for testing
    internal void AddEntries(TreeRouteBuilder builder, ActionDescriptorCollection actions)
    {
        var routeInfos = GetRouteInfos(actions.Items);

        // We're creating one TreeRouteLinkGenerationEntry per action. This allows us to match the intended
        // action by expected route values, and then use the TemplateBinder to generate the link.
        foreach (var routeInfo in routeInfos)
        {
            if (routeInfo.SuppressLinkGeneration)
            {
                continue;
            }

            var defaults = new RouteValueDictionary();
            foreach (var kvp in routeInfo.ActionDescriptor.RouteValues)
            {
                defaults.Add(kvp.Key, kvp.Value);
            }

            try
            {
                // We use the `NullRouter` as the route handler because we don't need to do anything for link
                // generations. The TreeRouter does it all for us.
                builder.MapOutbound(
                    NullRouter.Instance,
                    routeInfo.RouteTemplate,
                    defaults,
                    routeInfo.RouteName,
                    routeInfo.Order);
            }
            catch (RouteCreationException routeCreationException)
            {
                throw new RouteCreationException(
                          "An error occurred while adding a route to the route builder. " +
                          $"Route name '{routeInfo.RouteName}' and template '{routeInfo.RouteTemplate!.TemplateText}'.",
                          routeCreationException);
            }
        }

        // We're creating one AttributeRouteMatchingEntry per group, so we need to identify the distinct set of
        // groups. It's guaranteed that all members of the group have the same template and precedence,
        // so we only need to hang on to a single instance of the RouteInfo for each group.
        var groups = GetInboundRouteGroups(routeInfos);

        foreach (var group in groups)
        {
            var handler = _handlerFactory(group.ToArray());

            // Note that because we only support 'inline' defaults, each routeInfo group also has the same
            // set of defaults.
            //
            // We then inject the route group as a default for the matcher so it gets passed back to MVC
            // for use in action selection.
            builder.MapInbound(
                handler,
                group.Key.RouteTemplate,
                group.Key.RouteName,
                group.Key.Order);
        }
    }
        public override void AddEndpoint(MatcherEndpoint endpoint)
        {
            var handler = new RouteHandler(c =>
            {
                var feature      = c.Features.Get <IEndpointFeature>();
                feature.Endpoint = endpoint;
                feature.Invoker  = MatcherEndpoint.EmptyInvoker;

                return(Task.CompletedTask);
            });

            // MatcherEndpoint.Values contains the default values parsed from the template
            // as well as those specified with a literal. We need to separate those
            // for legacy cases.
            var defaults = endpoint.Defaults;

            for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
            {
                var parameter = endpoint.ParsedTemplate.Parameters[i];
                if (parameter.DefaultValue == null && defaults.ContainsKey(parameter.Name))
                {
                    throw new InvalidOperationException(
                              "The TreeRouter does not support non-inline default values.");
                }
            }

            _inner.MapInbound(
                handler,
                endpoint.ParsedTemplate,
                routeName: null,
                order: endpoint.Order);
        }
예제 #5
0
            public override void AddEntry(string template, MatcherEndpoint endpoint)
            {
                var handler = new RouteHandler(c =>
                {
                    c.Features.Get <IEndpointFeature>().Endpoint = endpoint;
                    return(Task.CompletedTask);
                });

                _inner.MapInbound(handler, TemplateParser.Parse(template), "default", 0);
            }
예제 #6
0
        public override Matcher Build()
        {
#pragma warning disable CS0618 // Type or member is obsolete
            var builder = new TreeRouteBuilder(
                NullLoggerFactory.Instance,
                new DefaultObjectPool <UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
                new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()), new TestServiceProvider()));
#pragma warning restore CS0618 // Type or member is obsolete

            var selector = new DefaultEndpointSelector();

            var groups = _endpoints
                         .GroupBy(e => (e.Order, e.RoutePattern.InboundPrecedence, e.RoutePattern.RawText))
                         .OrderBy(g => g.Key.Order)
                         .ThenBy(g => g.Key.InboundPrecedence);

            var routes = new RouteCollection();

            foreach (var group in groups)
            {
                var candidates = group.ToArray();

                // RouteEndpoint.Values contains the default values parsed from the template
                // as well as those specified with a literal. We need to separate those
                // for legacy cases.
                var endpoint = group.First();
                var defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults);
                for (var i = 0; i < endpoint.RoutePattern.Parameters.Count; i++)
                {
                    var parameter = endpoint.RoutePattern.Parameters[i];
                    if (parameter.Default != null)
                    {
                        defaults.Remove(parameter.Name);
                    }
                }

                builder.MapInbound(
                    new SelectorRouter(selector, candidates),
                    new RouteTemplate(endpoint.RoutePattern),
                    routeName: null,
                    order: endpoint.Order);
            }

            return(new TreeRouterMatcher(builder.Build()));
        }
예제 #7
0
        internal override Matcher CreateMatcher(MatcherEndpoint endpoint)
        {
            var builder = new TreeRouteBuilder(
                NullLoggerFactory.Instance,
                new DefaultObjectPool <UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
                new DefaultInlineConstraintResolver(Options.Create(new RouteOptions())));

            var handler = new RouteHandler(c =>
            {
                var feature      = c.Features.Get <IEndpointFeature>();
                feature.Endpoint = endpoint;
                feature.Invoker  = MatcherEndpoint.EmptyInvoker;

                return(Task.CompletedTask);
            });

            builder.MapInbound(handler, TemplateParser.Parse(endpoint.Template), "default", 0);

            return(new TreeRouterMatcher(builder.Build()));
        }
예제 #8
0
        // internal for testing
        internal void AddEntries(TreeRouteBuilder builder, ActionDescriptorCollection actions)
        {
            var routeInfos = GetRouteInfos(actions.Items);

            // We're creating one TreeRouteLinkGenerationEntry per action. This allows us to match the intended
            // action by expected route values, and then use the TemplateBinder to generate the link.
            foreach (var routeInfo in routeInfos)
            {
                builder.MapOutbound(
                    _handler,
                    routeInfo.RouteTemplate,
                    new RouteValueDictionary(routeInfo.ActionDescriptor.RouteValueDefaults),
                    routeInfo.RouteName,
                    routeInfo.Order);
            }

            // We're creating one AttributeRouteMatchingEntry per group, so we need to identify the distinct set of
            // groups. It's guaranteed that all members of the group have the same template and precedence,
            // so we only need to hang on to a single instance of the RouteInfo for each group.
            var distinctRouteInfosByGroup = GroupRouteInfosByGroupId(routeInfos);

            foreach (var routeInfo in distinctRouteInfosByGroup)
            {
                // Note that because we only support 'inline' defaults, each routeInfo group also has the same
                // set of defaults.
                //
                // We then inject the route group as a default for the matcher so it gets passed back to MVC
                // for use in action selection.
                var entry = builder.MapInbound(
                    _handler,
                    routeInfo.RouteTemplate,
                    routeInfo.RouteName,
                    routeInfo.Order);

                entry.Defaults[TreeRouter.RouteGroupKey] = routeInfo.RouteGroup;
            }
        }