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(); }
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(); }
// 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); }
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); }
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())); }
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())); }
// 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; } }