示例#1
0
        public async Task Execute(HttpContext context)
        {
            RouteData routeData = context.GetRouteData();

            var tasks = _appenders.Select((a, i) =>
            {
                // Create binder for the tempalte
                var templateBinder = new TemplateBinder(
                    context.RequestServices.GetRequiredService <UrlEncoder>(),
                    context.RequestServices.GetRequiredService <ObjectPool <UriBuildingContext> >(),
                    _routeTemplates[i].Item2,
                    null);

                // Transform the uri
                Uri fullUri = _routeTemplates[i].Item1 ?? context.Request.GetUri();
                string url  = templateBinder.BindValues(new RouteValueDictionary(routeData.Values));

                var ub  = new UriBuilder(fullUri);
                ub.Path = url;

                // Make the request
                return(a.GetAsync(ub.ToString(), context.RequestAborted));
            });

            // Wait for answer from all requests
            IAppenderResult[] results = await Task.WhenAll(tasks);

            // Merge reults
            object result = MergeResults(results);

            // Write output using formatters
            var actionContext = new ActionContext {
                HttpContext = context, RouteData = routeData
            };
            var objectResult = new OkObjectResult(result);
            await objectResult.ExecuteResultAsync(actionContext);
        }
示例#2
0
        public void Binding_WithEmptyAndNull_DefaultValues(
            string template,
            IDictionary <string, object> defaults,
            IDictionary <string, object> values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(TemplateParser.Parse(template, _inlineConstraintResolver),
                                            defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues: null, values: values);

            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);

            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);
                Assert.Equal(expected, boundTemplate);
            }
        }
        private static bool TryProcessPrefixTemplate(HttpRequest request, RoutePattern routePattern, out string path)
        {
            // TODO: Do you have a better way to process the prefix template?
            Contract.Assert(request != null);
            Contract.Assert(routePattern != null);

            HttpContext           httpContext    = request.HttpContext;
            TemplateBinderFactory factory        = request.HttpContext.RequestServices.GetRequiredService <TemplateBinderFactory>();
            TemplateBinder        templateBinder = factory.Create(routePattern);

            RouteValueDictionary ambientValues = GetAmbientValues(httpContext);

            var templateValuesResult = templateBinder.GetValues(ambientValues, request.RouteValues);

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

            if (!templateBinder.TryProcessConstraints(httpContext, templateValuesResult.CombinedValues, out var _, out var _))
            {
                path = default;
                return(false);
            }

            path = templateBinder.BindValues(templateValuesResult.AcceptedValues);
            int index = path.IndexOf("?", StringComparison.Ordinal); // remove the query string

            if (index >= 0)
            {
                path = path.Substring(0, index);
            }

            return(true);
        }
示例#4
0
        public void Binding_WithEmptyAndNull_DefaultValues(
            string template,
            RouteValueDictionary defaults,
            RouteValueDictionary values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(BinderFactory.Create(template, defaults));

            // Act & Assert
            var result = binder.GetValues(ambientValues: null, values: values);

            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);

            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);
                Assert.Equal(expected, boundTemplate);
            }
        }
        private string GetLink(
            RouteTemplate template,
            RouteValueDictionary defaults,
            RouteValueDictionary explicitValues,
            RouteValueDictionary ambientValues)
        {
            var templateBinder = new TemplateBinder(
                UrlEncoder.Default,
                _uriBuildingContextPool,
                template,
                defaults);

            var values = templateBinder.GetValues(ambientValues, explicitValues);

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

            //TODO: route constraint matching here

            return(templateBinder.BindValues(values.AcceptedValues));
        }
示例#6
0
        public void GetVirtualPathWithMultiSegmentWithOptionalParam(
            string template,
            IReadOnlyDictionary<string, object> defaults,
            IDictionary<string, object> ambientValues,
            IDictionary<string, object> values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(
                TemplateParser.Parse(template),
                defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues: ambientValues, values: values);
            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);
            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);
                Assert.Equal(expected, boundTemplate);
            }
        }
示例#7
0
        public void Binding_WithEmptyAndNull_DefaultValues(
            string template,
            IReadOnlyDictionary<string, object> defaults,
            IDictionary<string, object> values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(
                TemplateParser.Parse(template),
                defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues: null, values: values);
            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);
            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);
                Assert.Equal(expected, boundTemplate);
            }
        }
示例#8
0
        private static void RunTest(
            string template,
            IReadOnlyDictionary<string, object> defaults,
            IDictionary<string, object> ambientValues,
            IDictionary<string, object> values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(TemplateParser.Parse(template), defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues, values);
            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);
            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);

                // We want to chop off the query string and compare that using an unordered comparison
                var expectedParts = new PathAndQuery(expected);
                var actualParts = new PathAndQuery(boundTemplate);

                Assert.Equal(expectedParts.Path, actualParts.Path);

                if (expectedParts.Parameters == null)
                {
                    Assert.Null(actualParts.Parameters);
                }
                else
                {
                    Assert.Equal(expectedParts.Parameters.Count, actualParts.Parameters.Count);

                    foreach (var kvp in expectedParts.Parameters)
                    {
                        string value;
                        Assert.True(actualParts.Parameters.TryGetValue(kvp.Key, out value));
                        Assert.Equal(kvp.Value, value);
                    }
                }
            }
        }
        private VirtualPathData GenerateVirtualPath(
            VirtualPathContext context,
            OutboundRouteEntry entry,
            TemplateBinder binder)
        {
            // In attribute the context includes the values that are used to select this entry - typically
            // these will be the standard 'action', 'controller' and maybe 'area' tokens. However, we don't
            // want to pass these to the link generation code, or else they will end up as query parameters.
            //
            // So, we need to exclude from here any values that are 'required link values', but aren't
            // parameters in the template.
            //
            // Ex:
            //      template: api/Products/{action}
            //      required values: { id = "5", action = "Buy", Controller = "CoolProducts" }
            //
            //      result: { id = "5", action = "Buy" }
            var inputValues = new RouteValueDictionary();

            foreach (var kvp in context.Values)
            {
                if (entry.RequiredLinkValues.ContainsKey(kvp.Key))
                {
                    var parameter = entry.RouteTemplate.GetParameter(kvp.Key);

                    if (parameter == null)
                    {
                        continue;
                    }
                }

                inputValues.Add(kvp.Key, kvp.Value);
            }

            var bindingResult = binder.GetValues(context.AmbientValues, inputValues);

            if (bindingResult == null)
            {
                // A required parameter in the template didn't get a value.
                return(null);
            }

            var matched = RouteConstraintMatcher.Match(
                entry.Constraints,
                bindingResult.CombinedValues,
                context.HttpContext,
                this,
                RouteDirection.UrlGeneration,
                _constraintLogger);

            if (!matched)
            {
                // A constraint rejected this link.
                return(null);
            }

            var pathData = entry.Handler.GetVirtualPath(context);

            if (pathData != null)
            {
                // If path is non-null then the target router short-circuited, we don't expect this
                // in typical MVC scenarios.
                return(pathData);
            }

            var path = binder.BindValues(bindingResult.AcceptedValues);

            if (path == null)
            {
                return(null);
            }

            return(new VirtualPathData(this, path));
        }
        private static void RunTest(
            string template,
            RouteValueDictionary defaults,
            RouteValueDictionary ambientValues,
            RouteValueDictionary values,
            string expected)
        {
            // Arrange
            var binder = new TemplateBinder(
                UrlEncoder.Default,
                new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy()),
                TemplateParser.Parse(template),
                defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues, values);

            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);

            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);

                // We want to chop off the query string and compare that using an unordered comparison
                var expectedParts = new PathAndQuery(expected);
                var actualParts   = new PathAndQuery(boundTemplate);

                Assert.Equal(expectedParts.Path, actualParts.Path);

                if (expectedParts.Parameters == null)
                {
                    Assert.Null(actualParts.Parameters);
                }
                else
                {
                    Assert.Equal(expectedParts.Parameters.Count, actualParts.Parameters.Count);

                    foreach (var kvp in expectedParts.Parameters)
                    {
                        string value;
                        Assert.True(actualParts.Parameters.TryGetValue(kvp.Key, out value));
                        Assert.Equal(kvp.Value, value);
                    }
                }
            }
        }
示例#11
0
        public void GetVirtualPathWithMultiSegmentWithOptionalParam(
            string template,
            RouteValueDictionary defaults,
            RouteValueDictionary ambientValues,
            RouteValueDictionary values,
            string expected)
        {
            // Arrange
            var encoder = new UrlTestEncoder();
            var binder = new TemplateBinder(
                encoder,
                new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy(encoder)),
                TemplateParser.Parse(template),
                defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues: ambientValues, values: values);
            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);
            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);
                Assert.Equal(expected, boundTemplate);
            }
        }
示例#12
0
        private static void RunTest(
            string template,
            RouteValueDictionary defaults,
            RouteValueDictionary ambientValues,
            RouteValueDictionary values,
            string expected,
            UrlEncoder encoder = null)
        {
            // Arrange
            encoder = encoder ?? new UrlTestEncoder();

            var binder = new TemplateBinder(
                encoder,
                new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy(encoder)),
                TemplateParser.Parse(template),
                defaults);

            // Act & Assert
            var result = binder.GetValues(ambientValues, values);
            if (result == null)
            {
                if (expected == null)
                {
                    return;
                }
                else
                {
                    Assert.NotNull(result);
                }
            }

            var boundTemplate = binder.BindValues(result.AcceptedValues);
            if (expected == null)
            {
                Assert.Null(boundTemplate);
            }
            else
            {
                Assert.NotNull(boundTemplate);

                // We want to chop off the query string and compare that using an unordered comparison
                var expectedParts = new PathAndQuery(expected);
                var actualParts = new PathAndQuery(boundTemplate);

                Assert.Equal(expectedParts.Path, actualParts.Path);

                if (expectedParts.Parameters == null)
                {
                    Assert.Null(actualParts.Parameters);
                }
                else
                {
                    Assert.Equal(expectedParts.Parameters.Count, actualParts.Parameters.Count);

                    foreach (var kvp in expectedParts.Parameters)
                    {
                        string value;
                        Assert.True(actualParts.Parameters.TryGetValue(kvp.Key, out value));
                        Assert.Equal(kvp.Value, value);
                    }
                }
            }
        }