示例#1
0
        private string GetLink(MatcherEndpoint endpoint, LinkGeneratorContext context)
        {
            var templateBinder = new TemplateBinder(
                UrlEncoder.Default,
                _uriBuildingContextPool,
                new RouteTemplate(endpoint.RoutePattern),
                new RouteValueDictionary(endpoint.RoutePattern.Defaults));

            var templateValuesResult = templateBinder.GetValues(
                ambientValues: context.AmbientValues,
                explicitValues: context.ExplicitValues,
                endpoint.RequiredValues.Keys);

            if (templateValuesResult == null)
            {
                // We're missing one of the required values for this route.
                return(null);
            }

            if (!MatchesConstraints(context.HttpContext, endpoint, templateValuesResult.CombinedValues))
            {
                return(null);
            }

            var url = templateBinder.BindValues(templateValuesResult.AcceptedValues);

            return(Normalize(context, url));
        }
示例#2
0
        internal string MakeLink(
            HttpContext httpContext,
            MatcherEndpoint endpoint,
            RouteValueDictionary ambientValues,
            RouteValueDictionary explicitValues,
            LinkOptions options)
        {
            var templateBinder = new TemplateBinder(
                UrlEncoder.Default,
                _uriBuildingContextPool,
                new RouteTemplate(endpoint.RoutePattern),
                new RouteValueDictionary(endpoint.RoutePattern.Defaults));

            var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata <IRouteValuesAddressMetadata>();
            var templateValuesResult       = templateBinder.GetValues(
                ambientValues: ambientValues,
                explicitValues: explicitValues,
                requiredKeys: routeValuesAddressMetadata?.RequiredValues.Keys);

            if (templateValuesResult == null)
            {
                // We're missing one of the required values for this route.
                return(null);
            }

            if (!MatchesConstraints(httpContext, endpoint, templateValuesResult.CombinedValues))
            {
                return(null);
            }

            var url = templateBinder.BindValues(templateValuesResult.AcceptedValues);

            return(Normalize(url, options));
        }
示例#3
0
        private bool MatchesConstraints(
            HttpContext httpContext,
            MatcherEndpoint endpoint,
            RouteValueDictionary routeValues)
        {
            if (routeValues == null)
            {
                throw new ArgumentNullException(nameof(routeValues));
            }

            foreach (var kvp in endpoint.RoutePattern.Constraints)
            {
                var parameter            = endpoint.RoutePattern.GetParameter(kvp.Key); // may be null, that's ok
                var constraintReferences = kvp.Value;
                for (var i = 0; i < constraintReferences.Count; i++)
                {
                    var constraintReference = constraintReferences[i];
                    var matchProcessor      = _matchProcessorFactory.Create(parameter, constraintReference);
                    if (!matchProcessor.ProcessOutbound(httpContext, routeValues))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#4
0
        internal CandidateState(MatcherEndpoint endpoint, int score)
        {
            Endpoint = endpoint;
            Score    = score;

            IsValidCandidate = true;
            Values           = null;
        }
示例#5
0
        private MatcherEndpoint CreateEndpoint(ActionDescriptor action, string template, int order, object source)
        {
            RequestDelegate invokerDelegate = (context) =>
            {
                var values    = context.Features.Get <IEndpointFeature>().Values;
                var routeData = new RouteData();
                foreach (var kvp in values)
                {
                    if (kvp.Value != null)
                    {
                        routeData.Values.Add(kvp.Key, kvp.Value);
                    }
                }

                var actionContext = new ActionContext(context, routeData, action);

                var invoker = _invokerFactory.CreateInvoker(actionContext);
                return(invoker.InvokeAsync());
            };

            var metadata = new List <object>();

            // REVIEW: Used for debugging. Consider removing before release
            metadata.Add(source);
            metadata.Add(action);

            // Add filter descriptors to endpoint metadata
            if (action.FilterDescriptors != null && action.FilterDescriptors.Count > 0)
            {
                metadata.AddRange(action.FilterDescriptors.OrderBy(f => f, FilterDescriptorOrderComparer.Comparer).Select(f => f.Filter));
            }

            if (action.ActionConstraints != null && action.ActionConstraints.Count > 0)
            {
                foreach (var actionConstraint in action.ActionConstraints)
                {
                    if (actionConstraint is HttpMethodActionConstraint httpMethodActionConstraint)
                    {
                        metadata.Add(new HttpMethodEndpointConstraint(httpMethodActionConstraint.HttpMethods));
                    }
                }
            }

            var metadataCollection = new EndpointMetadataCollection(metadata);
            var endpoint           = new MatcherEndpoint(
                next => invokerDelegate,
                template,
                action.RouteValues,
                order,
                metadataCollection,
                action.DisplayName,
                address: null);

            return(endpoint);
        }
示例#6
0
            public override void AddEntry(string pattern, MatcherEndpoint endpoint)
            {
                var parsed = TemplateParser.Parse(pattern);

                _entries.Add(new Entry()
                {
                    Order      = 0,
                    Pattern    = parsed,
                    Precedence = RoutePrecedence.ComputeInbound(parsed),
                    Endpoint   = endpoint,
                });
            }
示例#7
0
        private MatcherEndpoint CreateEndpoint(
            ActionDescriptor action,
            string routeName,
            string template,
            object nonInlineDefaults,
            int order,
            object source,
            bool suppressLinkGeneration)
        {
            RequestDelegate invokerDelegate = (context) =>
            {
                var values    = context.Features.Get <IEndpointFeature>().Values;
                var routeData = new RouteData();
                foreach (var kvp in values)
                {
                    if (kvp.Value != null)
                    {
                        routeData.Values.Add(kvp.Key, kvp.Value);
                    }
                }

                var actionContext = new ActionContext(context, routeData, action);

                var invoker = _invokerFactory.CreateInvoker(actionContext);
                return(invoker.InvokeAsync());
            };

            var defaults = new RouteValueDictionary(nonInlineDefaults);

            EnsureRequiredValuesInDefaults(action.RouteValues, defaults);

            var metadataCollection = BuildEndpointMetadata(
                action,
                routeName,
                new RouteValueDictionary(action.RouteValues),
                source,
                suppressLinkGeneration);

            var endpoint = new MatcherEndpoint(
                next => invokerDelegate,
                RoutePatternFactory.Parse(template, defaults, constraints: null),
                order,
                metadataCollection,
                action.DisplayName);

            return(endpoint);
        }
        private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint 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?.Name,
            };

            entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults);
            return(entry);
        }
示例#9
0
        private MatcherEndpoint CreateEndpoint(
            ActionDescriptor action,
            string routeName,
            string template,
            object nonInlineDefaults,
            int order,
            object source)
        {
            RequestDelegate invokerDelegate = (context) =>
            {
                var values    = context.Features.Get <IEndpointFeature>().Values;
                var routeData = new RouteData();
                foreach (var kvp in values)
                {
                    if (kvp.Value != null)
                    {
                        routeData.Values.Add(kvp.Key, kvp.Value);
                    }
                }

                var actionContext = new ActionContext(context, routeData, action);

                var invoker = _invokerFactory.CreateInvoker(actionContext);
                return(invoker.InvokeAsync());
            };

            var metadataCollection = BuildEndpointMetadata(action, routeName, source);
            var endpoint           = new MatcherEndpoint(
                next => invokerDelegate,
                template,
                new RouteValueDictionary(nonInlineDefaults),
                new RouteValueDictionary(action.RouteValues),
                order,
                metadataCollection,
                action.DisplayName);

            // Use defaults after the endpoint is created as it merges both the inline and
            // non-inline defaults into one.
            EnsureRequiredValuesInDefaults(endpoint.RequiredValues, endpoint.Defaults);

            return(endpoint);
        }
示例#10
0
        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);
        }
示例#11
0
        private MatcherEndpoint CreateEndpoint(
            ActionDescriptor action,
            string routeName,
            string template,
            object nonInlineDefaults,
            int order,
            object source)
        {
            RequestDelegate invokerDelegate = (context) =>
            {
                var values    = context.Features.Get <IEndpointFeature>().Values;
                var routeData = new RouteData();
                foreach (var kvp in values)
                {
                    if (kvp.Value != null)
                    {
                        routeData.Values.Add(kvp.Key, kvp.Value);
                    }
                }

                var actionContext = new ActionContext(context, routeData, action);

                var invoker = _invokerFactory.CreateInvoker(actionContext);
                return(invoker.InvokeAsync());
            };

            var metadata = new List <object>();

            // REVIEW: Used for debugging. Consider removing before release
            metadata.Add(source);
            metadata.Add(action);

            if (!string.IsNullOrEmpty(routeName))
            {
                metadata.Add(new RouteNameMetadata(routeName));
            }

            // Add filter descriptors to endpoint metadata
            if (action.FilterDescriptors != null && action.FilterDescriptors.Count > 0)
            {
                metadata.AddRange(action.FilterDescriptors.OrderBy(f => f, FilterDescriptorOrderComparer.Comparer)
                                  .Select(f => f.Filter));
            }

            if (action.ActionConstraints != null && action.ActionConstraints.Count > 0)
            {
                foreach (var actionConstraint in action.ActionConstraints)
                {
                    if (actionConstraint is HttpMethodActionConstraint httpMethodActionConstraint)
                    {
                        metadata.Add(new HttpMethodEndpointConstraint(httpMethodActionConstraint.HttpMethods));
                    }
                }
            }

            var metadataCollection = new EndpointMetadataCollection(metadata);
            var endpoint           = new MatcherEndpoint(
                next => invokerDelegate,
                template,
                new RouteValueDictionary(nonInlineDefaults),
                new RouteValueDictionary(action.RouteValues),
                order,
                metadataCollection,
                action.DisplayName);

            // Use defaults after the endpoint is created as it merges both the inline and
            // non-inline defaults into one.
            EnsureRequiredValuesInDefaults(endpoint.RequiredValues, endpoint.Defaults);

            return(endpoint);
        }
 public abstract void AddEndpoint(MatcherEndpoint endpoint);
示例#13
0
 public abstract void AddEntry(string template, MatcherEndpoint endpoint);