public void Parse_ComplexSegment_PLP() { // Arrange var template = "{p1}-cool-{p2}"; var expected = new RouteTemplate(template, new List <TemplateSegment>()); expected.Segments.Add(new TemplateSegment()); expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", false, false, defaultValue: null, inlineConstraints: null)); expected.Parameters.Add(expected.Segments[0].Parts[0]); expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", false, false, defaultValue: null, inlineConstraints: null)); expected.Parameters.Add(expected.Segments[0].Parts[2]); // Act var actual = TemplateParser.Parse(template); // Assert Assert.Equal <RouteTemplate>(expected, actual, new TemplateEqualityComparer()); }
public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_PeriodAfterSlash() { // Arrange var template = "{p2}/.{p3?}"; var expected = new RouteTemplate(template, new List <TemplateSegment>()); expected.Segments.Add(new TemplateSegment()); expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", false, false, defaultValue: null, inlineConstraints: null)); expected.Segments.Add(new TemplateSegment()); expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral(".")); expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", false, true, null, null)); expected.Parameters.Add(expected.Segments[0].Parts[0]); expected.Parameters.Add(expected.Segments[1].Parts[1]); // Act var actual = TemplateParser.Parse(template); // Assert Assert.Equal <RouteTemplate>(expected, actual, new TemplateEqualityComparer()); }
public static TemplatePart ParseRouteParameter([NotNull] string routeParameter) { var isCatchAll = routeParameter.StartsWith("*", StringComparison.Ordinal); var isOptional = routeParameter.EndsWith("?", StringComparison.Ordinal); routeParameter = isCatchAll ? routeParameter.Substring(1) : routeParameter; routeParameter = isOptional ? routeParameter.Substring(0, routeParameter.Length - 1) : routeParameter; var parameterMatch = _parameterRegex.Match(routeParameter); if (!parameterMatch.Success) { return(TemplatePart.CreateParameter(name: string.Empty, isCatchAll: isCatchAll, isOptional: isOptional, defaultValue: null, inlineConstraints: null)); } var parameterName = parameterMatch.Groups["parameterName"].Value; // Add the default value if present var defaultValueGroup = parameterMatch.Groups["defaultValue"]; var defaultValue = GetDefaultValue(defaultValueGroup); // Register inline constraints if present var constraintGroup = parameterMatch.Groups["constraint"]; var inlineConstraints = GetInlineConstraints(constraintGroup); return(TemplatePart.CreateParameter(parameterName, isCatchAll, isOptional, defaultValue, inlineConstraints)); }
public void ParameterPart_ParameterNameAndDefaultAndParameterKindAndEnumerableOfParameterPolicies_ShouldMakeCopyOfParameterPolicies() { // Arrange (going through hoops to get an enumerable of RoutePatternParameterPolicyReference) const string name = "Id"; var defaults = new { a = "13", }; var x = new InlineConstraint("x"); var y = new InlineConstraint("y"); var z = new InlineConstraint("z"); var constraints = new[] { x, y, z }; var templatePart = TemplatePart.CreateParameter("t", false, false, null, constraints); var routePatternParameterPart = (RoutePatternParameterPart)templatePart.ToRoutePatternPart(); var policies = routePatternParameterPart.ParameterPolicies.ToList(); // Act var parameterPart = RoutePatternFactory.ParameterPart(name, defaults, RoutePatternParameterKind.Standard, policies); policies[0] = null; policies.RemoveAt(1); // Assert Assert.NotNull(parameterPart.ParameterPolicies); Assert.Equal(3, parameterPart.ParameterPolicies.Count); Assert.NotNull(parameterPart.ParameterPolicies[0]); Assert.NotNull(parameterPart.ParameterPolicies[1]); Assert.NotNull(parameterPart.ParameterPolicies[2]); }
public void Formats_template_parameters_correctly(string expected, string template, bool isCatchAll, bool isOptional) { var templatePart = TemplatePart.CreateParameter(template, isCatchAll, isOptional, defaultValue: null, inlineConstraints: null); var result = templatePart.ToTemplatePartString(); result.Should().Be(expected); }
public void Can_format_template_segements() { var expected = "{p}"; var segments = new List <TemplateSegment> { new TemplateSegment() }; segments[0].Parts.Add(TemplatePart.CreateParameter("p", false, false, defaultValue: null, inlineConstraints: null)); var result = segments[0].ToTemplateSegmentString(); result.Should().Be(expected); }
public void Configure(IApplicationBuilder app) { //We are building a url template from scratch, segment by segemtn, oldskool var segment = new TemplateSegment(); segment.Parts.Add(TemplatePart.CreateLiteral("page")); var segment2 = new TemplateSegment(); segment2.Parts.Add( TemplatePart.CreateParameter("title", isCatchAll: true, isOptional: true, defaultValue: null, inlineConstraints: new InlineConstraint[] {}) ); var segments = new TemplateSegment [] { segment, segment2 }; var template = new RouteTemplate("page", segments.ToList()); var templateMatcher = new TemplateMatcher(template, new RouteValueDictionary()); app.Use(async(context, next) => { await context.Response.WriteAsync("We are using two segments, one with Literal Template Part ('page') and the other with Parameter Template Part ('title')"); await context.Response.WriteAsync("\n\n"); await next.Invoke(); }); app.Use(async(context, next) => { var path1 = "/page/what"; var routeData = new RouteValueDictionary();//This dictionary will be populated by the parameter template part (in this case "title") var isMatch1 = templateMatcher.TryMatch(path1, routeData); await context.Response.WriteAsync($"{path1} is match? {isMatch1} => route data value for 'title' is {routeData["title"]} \n"); await next.Invoke(); }); app.Use(async(context, next) => { var path1 = "/page/the/old/man/and/the/sea"; var routeData = new RouteValueDictionary();//This dictionary will be populated by the parameter template part (in this case "title") var isMatch1 = templateMatcher.TryMatch(path1, routeData); await context.Response.WriteAsync($"{path1} is match? {isMatch1} => route data value for 'title' is {routeData["title"]} \n"); await next.Invoke(); }); app.Run(async context => { await context.Response.WriteAsync(""); }); }
public void Configure(IApplicationBuilder app) { //We are building a url template from scratch, segment by segemtn, oldskool var segment = new TemplateSegment(); segment.Parts.Add(TemplatePart.CreateLiteral("page")); var segment2 = new TemplateSegment(); segment2.Parts.Add(TemplatePart.CreateParameter("id", isCatchAll: false, isOptional: false, defaultValue: null, inlineConstraints: new InlineConstraint[] { new InlineConstraint("int") })); var segments = new TemplateSegment[] { segment, segment2 }; var template = new RouteTemplate("page", segments.ToList()); var templateMatcher = new TemplateMatcher(template, new RouteValueDictionary()); app.Use(async(context, next) => { await context.Response.WriteAsync("We are using one segment with two parts, one Literal Template Part ('page') and the other with Parameter Template Part ('id')."); await context.Response.WriteAsync("It is the equivalent of /page/{id:int}"); await context.Response.WriteAsync("\n\n"); await next.Invoke(); }); app.Use(async(context, next) => { var path1 = "/page/10"; var routeData = new RouteValueDictionary();//This dictionary will be populated by the parameter template part (in this case "title") var isMatch1 = templateMatcher.TryMatch(path1, routeData); await context.Response.WriteAsync($"{path1} is match? {isMatch1} => route data value for 'id' is {routeData["id"]} \n"); await next.Invoke(); }); app.Use(async(context, next) => { var path = "/page/a"; var routeData = new RouteValueDictionary();//This dictionary will be populated by the parameter template part (in this case "title") var isMatch1 = templateMatcher.TryMatch(path, routeData); await context.Response.WriteAsync($"{path} is match? {isMatch1} - as you can see TemplateMatcher does not give a damn about InlineConstraint. It is by design. \n"); }); }
public void Parse_OptionalParameter() { // Arrange var template = "{p?}"; var expected = new RouteTemplate(new List <TemplateSegment>()); expected.Segments.Add(new TemplateSegment()); expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p", false, true, defaultValue: null, inlineConstraint: null)); expected.Parameters.Add(expected.Segments[0].Parts[0]); // Act var actual = TemplateParser.Parse(template, _inlineConstraintResolver); // Assert Assert.Equal <RouteTemplate>(expected, actual, new TemplateEqualityComparer()); }
public void Configure(IApplicationBuilder app) { var apiSegment = new TemplateSegment(); apiSegment.Parts.Add(TemplatePart.CreateLiteral("api")); var serviceNameSegment = new TemplateSegment(); serviceNameSegment.Parts.Add( TemplatePart.CreateParameter("serviceName", isCatchAll: false, isOptional: true, defaultValue: null, inlineConstraints: new InlineConstraint[] { }) ); var segments = new TemplateSegment[] { apiSegment, serviceNameSegment }; var routeTemplate = new RouteTemplate("default", segments.ToList()); var templateMatcher = new TemplateMatcher(routeTemplate, new RouteValueDictionary()); app.Use(async(context, next) => { context.Response.Headers.Add("Content-type", "text/html"); var requestPath = context.Request.Path; var routeData = new RouteValueDictionary(); var isMatch = templateMatcher.TryMatch(requestPath, routeData); await context.Response.WriteAsync($"Request Path is <i>{requestPath}</i><br/>Match state is <b>{isMatch}</b><br/>Requested service name is {routeData["serviceName"]}"); await next.Invoke(); }); app.Run(async context => { await context.Response.WriteAsync(""); }); }
public void Parse_MultipleParameters() { // Arrange var template = "{p1}/{p2}/{*p3}"; var expected = new RouteTemplate(template, new List <TemplateSegment>()); expected.Segments.Add(new TemplateSegment()); expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", false, false, defaultValue: null, inlineConstraints: null)); expected.Parameters.Add(expected.Segments[0].Parts[0]); expected.Segments.Add(new TemplateSegment()); expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p2", false, false, defaultValue: null, inlineConstraints: null)); expected.Parameters.Add(expected.Segments[1].Parts[0]); expected.Segments.Add(new TemplateSegment()); expected.Segments[2].Parts.Add(TemplatePart.CreateParameter("p3", true, false, defaultValue: null, inlineConstraints: null)); expected.Parameters.Add(expected.Segments[2].Parts[0]); // Act var actual = TemplateParser.Parse(template); // Assert Assert.Equal <RouteTemplate>(expected, actual, new TemplateEqualityComparer()); }
[InlineData(@"{p1:regex(([{{(])\w+)}", @"regex(([{(])\w+)")] // Not balanced { public void Parse_RegularExpressions(string template, string constraint) { // Arrange var expected = new RouteTemplate(template, new List <TemplateSegment>()); expected.Segments.Add(new TemplateSegment()); var c = new InlineConstraint(constraint); expected.Segments[0].Parts.Add( TemplatePart.CreateParameter("p1", false, false, defaultValue: null, inlineConstraints: new List <InlineConstraint> { c })); expected.Parameters.Add(expected.Segments[0].Parts[0]); // Act var actual = TemplateParser.Parse(template); // Assert Assert.Equal <RouteTemplate>(expected, actual, new TemplateEqualityComparer()); }
public static TemplatePart ParseRouteParameter([NotNull] string routeParameter) { if (routeParameter.Length == 0) { return(TemplatePart.CreateParameter( name: string.Empty, isCatchAll: false, isOptional: false, defaultValue: null, inlineConstraints: null)); } var startIndex = 0; var endIndex = routeParameter.Length - 1; var isCatchAll = false; var isOptional = false; if (routeParameter[0] == '*') { isCatchAll = true; startIndex++; } if (routeParameter[endIndex] == '?') { isOptional = true; endIndex--; } var currentIndex = startIndex; // Parse parameter name var parameterName = string.Empty; while (currentIndex <= endIndex) { var currentChar = routeParameter[currentIndex]; if ((currentChar == ':' || currentChar == '=') && startIndex != currentIndex) { // Parameter names are allowed to start with delimiters used to denote constraints or default values. // i.e. "=foo" or ":bar" would be treated as parameter names rather than default value or constraint // specifications. parameterName = routeParameter.Substring(startIndex, currentIndex - startIndex); // Roll the index back and move to the constraint parsing stage. currentIndex--; break; } else if (currentIndex == endIndex) { parameterName = routeParameter.Substring(startIndex, currentIndex - startIndex + 1); } currentIndex++; } var parseResults = ParseConstraints(routeParameter, currentIndex, endIndex); currentIndex = parseResults.CurrentIndex; string defaultValue = null; if (currentIndex <= endIndex && routeParameter[currentIndex] == '=') { defaultValue = routeParameter.Substring(currentIndex + 1, endIndex - currentIndex); } return(TemplatePart.CreateParameter(parameterName, isCatchAll, isOptional, defaultValue, parseResults.Constraints)); }