public void GetValues_SuccessfullyMatchesRouteValues_ForExplicitNullValue_AndEmptyStringDefault() { // Arrange var expected = "/Home/Index"; var template = "Home/Index"; var defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }); var ambientValues = new RouteValueDictionary(new { controller = "Rail", action = "Schedule", area = "Travel" }); var explicitValues = new RouteValueDictionary(new { controller = "Home", action = "Index", area = (string)null }); var binder = new TemplateBinder( UrlEncoder.Default, new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy()), TemplateParser.Parse(template), defaults); // Act1 var result = binder.GetValues(ambientValues, explicitValues); // Assert1 Assert.NotNull(result); // Act2 var boundTemplate = binder.BindValues(result.AcceptedValues); // Assert2 Assert.NotNull(boundTemplate); Assert.Equal(expected, boundTemplate); }
private void RunTest( string template, RouteValueDictionary defaults, RouteValueDictionary ambientValues, RouteValueDictionary values, string expected, UrlEncoder encoder = null) { // Arrange var binderFactory = encoder == null ? BinderFactory : new RoutePatternBinderFactory(encoder, new DefaultObjectPoolProvider()); var binder = new TemplateBinder(binderFactory.Create(template, defaults ?? new RouteValueDictionary())); // 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 TemplateBinder_KeepsExplicitlySuppliedRouteValues_OnFailedRouetMatch() { // Arrange var template = "{area?}/{controller=Home}/{action=Index}/{id?}"; var binder = new TemplateBinder( UrlEncoder.Default, new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy()), TemplateParser.Parse(template), defaults: null); var ambientValues = new RouteValueDictionary(); var routeValues = new RouteValueDictionary(new { controller = "Test", action = "Index" }); // Act var templateValuesResult = binder.GetValues(ambientValues, routeValues); var boundTemplate = binder.BindValues(templateValuesResult.AcceptedValues); // Assert Assert.Null(boundTemplate); Assert.Equal(2, templateValuesResult.CombinedValues.Count); object routeValue; Assert.True(templateValuesResult.CombinedValues.TryGetValue("controller", out routeValue)); Assert.Equal("Test", routeValue?.ToString()); Assert.True(templateValuesResult.CombinedValues.TryGetValue("action", out routeValue)); Assert.Equal("Index", routeValue?.ToString()); }
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)); }
internal string MakeLink( HttpContext httpContext, RouteEndpoint endpoint, RouteValueDictionary ambientValues, RouteValueDictionary explicitValues, LinkOptions options) { var templateBinder = new TemplateBinder( UrlEncoder.Default, _uriBuildingContextPool, 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)); }
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); } } } }
/// <inheritdoc /> public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureBinder(context.HttpContext); EnsureLoggers(context.HttpContext); var values = _binder.GetValues(context.AmbientValues, context.Values); if (values == null) { // We're missing one of the required values for this route. return(null); } if (!RouteConstraintMatcher.Match( Constraints, values.CombinedValues, context.HttpContext, this, RouteDirection.UrlGeneration, _logger )) { return(null); } context.Values = values.CombinedValues; var pathData = OnVirtualPathGenerated(context); if (pathData != null) { // If the target generates a value then that can short circuit. return(pathData); } // If we can produce a value go ahead and do it, the caller can check context.IsBound // to see if the values were validated. // When we still cannot produce a value, this should return null. var virtualPath = _binder.BindValues(values.AcceptedValues); if (virtualPath == null) { return(null); } pathData = new VirtualPathData(this, virtualPath); if (DataTokens != null) { foreach (var dataToken in DataTokens) { pathData.DataTokens.Add(dataToken.Key, dataToken.Value); } } return(pathData); }
/// <summary> /// 使用mvc路由模版绑定参数 /// </summary> /// <param name="template">路由模版</param> /// <param name="values">参数</param> /// <returns></returns> private string BoundTemplate(string template, RouteValueDictionary values) { var binder = new TemplateBinder( UrlEncoder.Default, new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy(UrlEncoder.Default)), TemplateParser.Parse(template), null ); // Act & Assert var result = binder.GetValues(new RouteValueDictionary(), values); return(binder.BindValues(result.AcceptedValues)); }
/// <summary> /// 使用mvc路由模版绑定参数 /// </summary> /// <param name="template">路由模版</param> /// <param name="values">参数</param> /// <returns></returns> private string BoundTemplate(string template, RouteValueDictionary values) { var binder = new TemplateBinder( UrlEncoder.Default, null, TemplateParser.Parse(template), null ); // Act & Assert var result = binder.GetValues(new RouteValueDictionary(), values); return(binder.BindValues(result.AcceptedValues)); }
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); } }
public void Binding_WithEmptyAndNull_DefaultValues( string template, RouteValueDictionary defaults, 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: 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); } }
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); } }
public void TemplateBinder_KeepsExplicitlySuppliedRouteValues_OnFailedRouetMatch() { // Arrange var template = "{area?}/{controller=Home}/{action=Index}/{id?}"; var binder = new TemplateBinder(BinderFactory.Create(template)); var ambientValues = new RouteValueDictionary(); var routeValues = new RouteValueDictionary(new { controller = "Test", action = "Index" }); // Act var templateValuesResult = binder.GetValues(ambientValues, routeValues); var boundTemplate = binder.BindValues(templateValuesResult.AcceptedValues); // Assert Assert.Null(boundTemplate); Assert.Equal(2, templateValuesResult.CombinedValues.Count); object routeValue; Assert.True(templateValuesResult.CombinedValues.TryGetValue("controller", out routeValue)); Assert.Equal("Test", routeValue?.ToString()); Assert.True(templateValuesResult.CombinedValues.TryGetValue("action", out routeValue)); Assert.Equal("Index", routeValue?.ToString()); }
public void GetVirtualPathWithMultiSegmentWithOptionalParam( string template, RouteValueDictionary defaults, RouteValueDictionary ambientValues, RouteValueDictionary values, string expected) { // Arrange var binder = new TemplateBinder(BinderFactory.Create(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 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 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); } } } }
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 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)); }