parent
e450e1fa32
commit
54e96bd404
|
|
@ -58,8 +58,7 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
var segment = PathSegments[i];
|
||||
for (var j = 0; j < segment.Parts.Count; j++)
|
||||
{
|
||||
var parameter = segment.Parts[j] as RoutePatternParameter;
|
||||
if (parameter != null)
|
||||
if (segment.Parts[j] is RoutePatternParameter parameter)
|
||||
{
|
||||
parameters.Add(parameter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,9 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
throw new ArgumentNullException(nameof(pattern));
|
||||
}
|
||||
|
||||
if (IsInvalidPattern(pattern))
|
||||
{
|
||||
throw new RoutePatternException(pattern, Resources.TemplateRoute_InvalidRouteTemplate);
|
||||
}
|
||||
var trimmedPattern = TrimPrefix(pattern);
|
||||
|
||||
var context = new TemplateParserContext(pattern);
|
||||
var builder = RoutePatternBuilder.Create(pattern);
|
||||
var context = new TemplateParserContext(trimmedPattern);
|
||||
var segments = new List<RoutePatternPathSegment>();
|
||||
|
||||
while (context.MoveNext())
|
||||
|
|
@ -69,6 +65,7 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
|
||||
if (IsAllValid(context, segments))
|
||||
{
|
||||
var builder = RoutePatternBuilder.Create(pattern);
|
||||
for (var i = 0; i < segments.Count; i++)
|
||||
{
|
||||
builder.PathSegments.Add(segments[i]);
|
||||
|
|
@ -257,7 +254,7 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
private static bool ParseLiteral(TemplateParserContext context, List<RoutePatternPart> parts)
|
||||
{
|
||||
context.Mark();
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (context.Current == Separator)
|
||||
|
|
@ -469,10 +466,21 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool IsInvalidPattern(string routeTemplate)
|
||||
private static string TrimPrefix(string routePattern)
|
||||
{
|
||||
return routeTemplate.StartsWith("~", StringComparison.Ordinal) ||
|
||||
routeTemplate.StartsWith("/", StringComparison.Ordinal);
|
||||
if (routePattern.StartsWith("~/", StringComparison.Ordinal))
|
||||
{
|
||||
return routePattern.Substring(2);
|
||||
}
|
||||
else if (routePattern.StartsWith("/", StringComparison.Ordinal))
|
||||
{
|
||||
return routePattern.Substring(1);
|
||||
}
|
||||
else if (routePattern.StartsWith("~", StringComparison.Ordinal))
|
||||
{
|
||||
throw new RoutePatternException(routePattern, Resources.TemplateRoute_InvalidRouteTemplate);
|
||||
}
|
||||
return routePattern;
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{DebuggerToString()}")]
|
||||
|
|
@ -555,8 +563,8 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
}
|
||||
else if (_mark.HasValue)
|
||||
{
|
||||
return _template.Substring(0, _mark.Value) +
|
||||
"|" +
|
||||
return _template.Substring(0, _mark.Value) +
|
||||
"|" +
|
||||
_template.Substring(_mark.Value, _index - _mark.Value) +
|
||||
"|" +
|
||||
_template.Substring(_index);
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
=> string.Format(CultureInfo.CurrentCulture, GetString("TemplateRoute_InvalidParameterName"), p0);
|
||||
|
||||
/// <summary>
|
||||
/// The route template cannot start with a '/' or '~' character.
|
||||
/// The route template cannot start with a '~' character.
|
||||
/// </summary>
|
||||
internal static string TemplateRoute_InvalidRouteTemplate
|
||||
{
|
||||
|
|
@ -229,7 +229,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The route template cannot start with a '/' or '~' character.
|
||||
/// The route template cannot start with a '~' character.
|
||||
/// </summary>
|
||||
internal static string FormatTemplateRoute_InvalidRouteTemplate()
|
||||
=> GetString("TemplateRoute_InvalidRouteTemplate");
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@
|
|||
<value>The route parameter name '{0}' is invalid. Route parameter names must be non-empty and cannot contain these characters: '{{', '}}', '/'. The '?' character marks a parameter as optional, and can occur only at the end of the parameter. The '*' character marks a parameter as catch-all, and can occur only at the start of the parameter.</value>
|
||||
</data>
|
||||
<data name="TemplateRoute_InvalidRouteTemplate" xml:space="preserve">
|
||||
<value>The route template cannot start with a '/' or '~' character.</value>
|
||||
<value>The route template cannot start with a '~' character unless followed by a '/'.</value>
|
||||
</data>
|
||||
<data name="TemplateRoute_MismatchedParameter" xml:space="preserve">
|
||||
<value>There is an incomplete parameter in the route template. Check that each '{' character has a matching '}' character.</value>
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
// If it's a parameter subsegment, examine the current value to see if it matches the new value
|
||||
var parameterName = parameter.Name;
|
||||
|
||||
object newParameterValue;
|
||||
var hasNewParameterValue = values.TryGetValue(parameterName, out newParameterValue);
|
||||
var hasNewParameterValue = values.TryGetValue(parameterName, out var newParameterValue);
|
||||
|
||||
object currentParameterValue = null;
|
||||
var hasCurrentParameterValue = ambientValues != null &&
|
||||
|
|
@ -179,8 +178,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
continue;
|
||||
}
|
||||
|
||||
object value;
|
||||
if (values.TryGetValue(filter.Key, out value))
|
||||
if (values.TryGetValue(filter.Key, out var value))
|
||||
{
|
||||
if (!RoutePartsEqual(value, filter.Value))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Routing.Template
|
|||
|
||||
try
|
||||
{
|
||||
var inner = Microsoft.AspNetCore.Dispatcher.Patterns.RoutePattern.Parse(routeTemplate);
|
||||
var inner = RoutePattern.Parse(routeTemplate);
|
||||
return new RouteTemplate(inner);
|
||||
}
|
||||
catch (ArgumentException ex) when (ex.InnerException is RoutePatternException)
|
||||
|
|
|
|||
|
|
@ -622,12 +622,16 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
"a literal string.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_CannotStartWithSlash()
|
||||
[Theory]
|
||||
[InlineData("/foo")]
|
||||
[InlineData("~/foo")]
|
||||
public void ValidTemplate_CanStartWithSlashOrTildeSlash(string routePattern)
|
||||
{
|
||||
ExceptionAssert.Throws<RoutePatternException>(
|
||||
() => RoutePatternParser.Parse("/foo"),
|
||||
"The route template cannot start with a '/' or '~' character.");
|
||||
// Arrange & Act
|
||||
var pattern = RoutePatternParser.Parse(routePattern);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(routePattern, pattern.RawText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -635,7 +639,7 @@ namespace Microsoft.AspNetCore.Dispatcher.Patterns
|
|||
{
|
||||
ExceptionAssert.Throws<RoutePatternException>(
|
||||
() => RoutePatternParser.Parse("~foo"),
|
||||
"The route template cannot start with a '/' or '~' character.");
|
||||
"The route template cannot start with a '~' character unless followed by a '/'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Dispatcher.Patterns;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.WebEncoders.Testing;
|
||||
using Xunit;
|
||||
|
|
@ -651,6 +650,28 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
UrlEncoder.Default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUrlWithLeadingTildeSlash()
|
||||
{
|
||||
RunTest(
|
||||
"~/foo",
|
||||
null,
|
||||
null,
|
||||
new DispatcherValueCollection(new { }),
|
||||
"/UrlEncode[[foo]]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUrlWithLeadingSlash()
|
||||
{
|
||||
RunTest(
|
||||
"/foo",
|
||||
null,
|
||||
null,
|
||||
new DispatcherValueCollection(new { }),
|
||||
"/UrlEncode[[foo]]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUrlWithCatchAllWithValue()
|
||||
{
|
||||
|
|
@ -1192,8 +1213,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
|
||||
foreach (var kvp in expectedParts.Parameters)
|
||||
{
|
||||
string value;
|
||||
Assert.True(actualParts.Parameters.TryGetValue(kvp.Key, out value));
|
||||
Assert.True(actualParts.Parameters.TryGetValue(kvp.Key, out var value));
|
||||
Assert.Equal(kvp.Value, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -765,13 +765,16 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
|
|||
"Parameter name: routeTemplate");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_CannotStartWithSlash()
|
||||
[Theory]
|
||||
[InlineData("/foo")]
|
||||
[InlineData("~/foo")]
|
||||
public void ValidTemplate_CanStartWithSlashOrTildeSlash(string routeTemplate)
|
||||
{
|
||||
ExceptionAssert.Throws<ArgumentException>(
|
||||
() => TemplateParser.Parse("/foo"),
|
||||
"The route template cannot start with a '/' or '~' character." + Environment.NewLine +
|
||||
"Parameter name: routeTemplate");
|
||||
// Arrange & Act
|
||||
var pattern = TemplateParser.Parse(routeTemplate);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(routeTemplate, pattern.TemplateText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -779,7 +782,7 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
|
|||
{
|
||||
ExceptionAssert.Throws<ArgumentException>(
|
||||
() => TemplateParser.Parse("~foo"),
|
||||
"The route template cannot start with a '/' or '~' character." + Environment.NewLine +
|
||||
"The route template cannot start with a '~' character unless followed by a '/'." + Environment.NewLine +
|
||||
"Parameter name: routeTemplate");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue