/// <summary> /// Processes one attribute route /// </summary> /// <param name="action">Action to process</param> /// <returns>Route information</returns> private AttributeRouteInfo ProcessAttributeRoute(ControllerActionDescriptor action) { string constraint; action.RouteValues.TryGetValue(TreeRouter.RouteGroupKey, out constraint); if (string.IsNullOrEmpty(constraint)) { // This can happen if an ActionDescriptor has a route template, but doesn't have one of our // special route group constraints. This is a good indication that the user is using a 3rd party // routing system, or has customized their ADs in a way that we can no longer understand them. // // We just treat this case as an 'opt-out' of our attribute routing system. return(null); } var template = TemplateParser.Parse(action.AttributeRouteInfo.Template); var info = new AttributeRouteInfo { Constraints = GetConstraints(action.AttributeRouteInfo.Template, template), Defaults = GetDefaults(action, template), Optional = new List <string>(), Order = action.AttributeRouteInfo.Order, Precedence = RoutePrecedence.ComputeOutbound(template), }; _parser.Parse(template, info); return(info); }
private OutboundRouteEntry CreateOutboundRouteEntry(RouteEndpoint endpoint) { var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata <IRouteValuesAddressMetadata>(); var entry = new OutboundRouteEntry() { Handler = NullRouter.Instance, Order = endpoint.Order, Precedence = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern), RequiredLinkValues = new RouteValueDictionary(routeValuesAddressMetadata?.RequiredValues), RouteTemplate = new RouteTemplate(endpoint.RoutePattern), Data = endpoint, RouteName = routeValuesAddressMetadata?.RouteName, }; entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults); return(entry); }
public void AttributeRoute_GetEntries_CreatesOutboundEntry_WithDefault() { // Arrange var actions = new List <ActionDescriptor>() { new ActionDescriptor() { AttributeRouteInfo = new AttributeRouteInfo() { Template = "api/Blog/{*slug=hello}", Name = "BLOG_INDEX", Order = 17, }, RouteValues = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { TreeRouter.RouteGroupKey, "1" } }, RouteValueDefaults = new Dictionary <string, object>() { { "controller", "Blog" }, { "action", "Index" }, }, }, }; var builder = CreateBuilder(); var actionDescriptorProvider = CreateActionDescriptorProvider(actions); var route = CreateRoute(CreateHandler().Object, actionDescriptorProvider.Object); // Act route.AddEntries(builder, actionDescriptorProvider.Object.ActionDescriptors); // Assert Assert.Collection( builder.OutboundEntries, e => { Assert.Empty(e.Constraints); Assert.Equal(new RouteValueDictionary(new { slug = "hello" }), e.Defaults); Assert.Equal(RoutePrecedence.ComputeOutbound(e.RouteTemplate), e.Precedence); Assert.Equal("BLOG_INDEX", e.RouteName); Assert.Equal(17, e.Order); Assert.Equal(actions[0].RouteValueDefaults.ToArray(), e.RequiredLinkValues.ToArray()); Assert.Equal("api/Blog/{*slug=hello}", e.RouteTemplate.TemplateText); }); }
/// <summary> /// Processes one attribute route /// </summary> /// <param name="action">Action to process</param> /// <returns>Route information</returns> private AttributeRouteInfo ProcessAttributeRoute(ControllerActionDescriptor action) { var template = TemplateParser.Parse(action.AttributeRouteInfo.Template); var info = new AttributeRouteInfo { Constraints = GetConstraints(action.AttributeRouteInfo.Template, template), Defaults = GetDefaults(action, template), Optional = new List <string>(), Order = action.AttributeRouteInfo.Order, Precedence = RoutePrecedence.ComputeOutbound(template), }; _parser.Parse(template, info); return(info); }
private OutboundRouteEntry CreateOutboundRouteEntry( RouteEndpoint endpoint, IReadOnlyDictionary <string, object> requiredValues, string routeName) { var entry = new OutboundRouteEntry() { Handler = NullRouter.Instance, Order = endpoint.Order, Precedence = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern), RequiredLinkValues = new RouteValueDictionary(requiredValues), RouteTemplate = new RouteTemplate(endpoint.RoutePattern), Data = endpoint, RouteName = routeName, }; entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults); return(entry); }
internal RoutePattern( string rawText, Dictionary <string, object> defaults, Dictionary <string, IReadOnlyList <RoutePatternConstraintReference> > constraints, RoutePatternParameterPart[] parameters, RoutePatternPathSegment[] pathSegments) { Debug.Assert(defaults != null); Debug.Assert(constraints != null); Debug.Assert(parameters != null); Debug.Assert(pathSegments != null); RawText = rawText; Defaults = defaults; Constraints = constraints; Parameters = parameters; PathSegments = pathSegments; InboundPrecedence = RoutePrecedence.ComputeInbound(this); OutboundPrecedence = RoutePrecedence.ComputeOutbound(this); }
internal RoutePattern( string rawText, IReadOnlyDictionary <string, object> defaults, IReadOnlyDictionary <string, IReadOnlyList <RoutePatternParameterPolicyReference> > parameterPolicies, IReadOnlyList <RoutePatternParameterPart> parameters, IReadOnlyList <RoutePatternPathSegment> pathSegments) { Debug.Assert(defaults != null); Debug.Assert(parameterPolicies != null); Debug.Assert(parameters != null); Debug.Assert(pathSegments != null); RawText = rawText; Defaults = defaults; ParameterPolicies = parameterPolicies; Parameters = parameters; PathSegments = pathSegments; InboundPrecedence = RoutePrecedence.ComputeInbound(this); OutboundPrecedence = RoutePrecedence.ComputeOutbound(this); }
private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint) { var routeNameMetadata = endpoint.Metadata.GetMetadata <IRouteNameMetadata>(); var entry = new OutboundRouteEntry() { Handler = NullRouter.Instance, Order = endpoint.Order, Precedence = RoutePrecedence.ComputeOutbound(endpoint.ParsedTemplate), RequiredLinkValues = endpoint.RequiredValues, RouteTemplate = endpoint.ParsedTemplate, Data = endpoint, RouteName = routeNameMetadata?.Name, }; // TODO: review. These route constriants should be constructed when the endpoint // is built. This way they can be checked for validity on app startup too var constraintBuilder = new RouteConstraintBuilder( _inlineConstraintResolver, endpoint.ParsedTemplate.TemplateText); foreach (var parameter in endpoint.ParsedTemplate.Parameters) { if (parameter.InlineConstraints != null) { if (parameter.IsOptional) { constraintBuilder.SetOptional(parameter.Name); } foreach (var constraint in parameter.InlineConstraints) { constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint); } } } entry.Constraints = constraintBuilder.Build(); entry.Defaults = endpoint.Defaults; return(entry); }
/// <summary> /// Adds a new outbound route to the <see cref="TreeRouter"/>. /// </summary> /// <param name="handler">The <see cref="IRouter"/> for handling the link generation.</param> /// <param name="routeTemplate">The <see cref="RouteTemplate"/> of the route.</param> /// <param name="requiredLinkValues">The <see cref="RouteValueDictionary"/> containing the route values.</param> /// <param name="routeName">The route name.</param> /// <param name="order">The route order.</param> /// <returns>The <see cref="OutboundRouteEntry"/>.</returns> public OutboundRouteEntry MapOutbound( IRouter handler, RouteTemplate routeTemplate, RouteValueDictionary requiredLinkValues, string routeName, int order) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } if (routeTemplate == null) { throw new ArgumentNullException(nameof(routeTemplate)); } if (requiredLinkValues == null) { throw new ArgumentNullException(nameof(requiredLinkValues)); } var entry = new OutboundRouteEntry() { Handler = handler, Order = order, Precedence = RoutePrecedence.ComputeOutbound(routeTemplate), RequiredLinkValues = requiredLinkValues, RouteName = routeName, RouteTemplate = routeTemplate, }; var constraintBuilder = new RouteConstraintBuilder(_constraintResolver, routeTemplate.TemplateText); foreach (var parameter in routeTemplate.Parameters) { if (parameter.InlineConstraints != null) { if (parameter.IsOptional) { constraintBuilder.SetOptional(parameter.Name); } foreach (var constraint in parameter.InlineConstraints) { constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint); } } } entry.Constraints = constraintBuilder.Build(); entry.Defaults = new RouteValueDictionary(); foreach (var parameter in entry.RouteTemplate.Parameters) { if (parameter.DefaultValue != null) { entry.Defaults.Add(parameter.Name, parameter.DefaultValue); } } OutboundEntries.Add(entry); return(entry); }