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