public override Matcher Build() { var builder = new TreeRouteBuilder( NullLoggerFactory.Instance, new DefaultObjectPool <UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()), new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()), new TestServiceProvider())); 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; } }