Remove string.Split from routing
This change removes the call to string.Split and a few substrings, and replaces it with a tokenizer API. The tokenizer isn't really optimized right now for compute - it should probably be an iterator- but it's a significant improvement on what we're doing.
This commit is contained in:
parent
2f8dba6659
commit
371d4e62da
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Routing.Internal
|
||||
{
|
||||
public struct PathSegment : IEquatable<PathSegment>, IEquatable<string>
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly int _start;
|
||||
private readonly int _length;
|
||||
|
||||
private string _segment;
|
||||
|
||||
public PathSegment(string path, int start, int length)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
if (start < 1 || start >= path.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(start));
|
||||
}
|
||||
|
||||
if (length < 0 || start + length > path.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length));
|
||||
}
|
||||
|
||||
_path = path;
|
||||
_start = start;
|
||||
_length = length;
|
||||
|
||||
_segment = null;
|
||||
}
|
||||
|
||||
public int Length => _length;
|
||||
|
||||
public string GetRemainingPath()
|
||||
{
|
||||
if (_path == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return _path.Substring(_start);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as PathSegment?;
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Equals(other.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (_path == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return StringComparer.OrdinalIgnoreCase.GetHashCode(ToString());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (_path == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (_segment == null)
|
||||
{
|
||||
_segment = _path.Substring(_start, _length);
|
||||
}
|
||||
|
||||
return _segment;
|
||||
}
|
||||
|
||||
public bool Equals(PathSegment other)
|
||||
{
|
||||
if (_path == null)
|
||||
{
|
||||
return other._path == null;
|
||||
}
|
||||
|
||||
if (other._length != _length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return string.Compare(
|
||||
_path,
|
||||
_start,
|
||||
other._path,
|
||||
other._start,
|
||||
_length,
|
||||
StringComparison.OrdinalIgnoreCase) == 0;
|
||||
}
|
||||
|
||||
public bool Equals(string other)
|
||||
{
|
||||
if (_path == null)
|
||||
{
|
||||
return other == null;
|
||||
}
|
||||
|
||||
if (other.Length != _length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return string.Compare(_path, _start, other, 0, _length, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
}
|
||||
|
||||
public static bool operator ==(PathSegment x, PathSegment y)
|
||||
{
|
||||
return x.Equals(y);
|
||||
}
|
||||
|
||||
public static bool operator !=(PathSegment x, PathSegment y)
|
||||
{
|
||||
return !x.Equals(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNet.Http;
|
||||
|
||||
namespace Microsoft.AspNet.Routing.Internal
|
||||
{
|
||||
public struct PathTokenizer : IReadOnlyList<PathSegment>
|
||||
{
|
||||
private readonly string _path;
|
||||
private int _count;
|
||||
|
||||
public PathTokenizer(PathString path)
|
||||
{
|
||||
_path = path.Value;
|
||||
_count = -1;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_count == -1)
|
||||
{
|
||||
// We haven't computed the real count of segments yet.
|
||||
if (_path.Length == 0)
|
||||
{
|
||||
// The empty string has length of 0.
|
||||
_count = 0;
|
||||
return _count;
|
||||
}
|
||||
|
||||
// A string of length 1 must be "/" - all PathStrings start with '/'
|
||||
if (_path.Length == 1)
|
||||
{
|
||||
// We treat this as empty - there's nothing to parse here for routing, because routing ignores
|
||||
// a trailing slash.
|
||||
Debug.Assert(_path[0] == '/');
|
||||
_count = 0;
|
||||
return _count;
|
||||
}
|
||||
|
||||
// This is a non-trival PathString
|
||||
_count = 1;
|
||||
|
||||
// Since a non-empty PathString must begin with a `/`, we can just count the number of occurrences
|
||||
// of `/` to find the number of segments. However, we don't look at the last character, because
|
||||
// routing ignores a trailing slash.
|
||||
for (var i = 1; i < _path.Length - 1; i++)
|
||||
{
|
||||
if (_path[i] == '/')
|
||||
{
|
||||
_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _count;
|
||||
}
|
||||
}
|
||||
|
||||
public PathSegment this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index >= Count)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
|
||||
var currentSegmentIndex = 0;
|
||||
var currentSegmentStart = 1;
|
||||
|
||||
// Skip the first `/`.
|
||||
var delimiterIndex = 1;
|
||||
while ((delimiterIndex = _path.IndexOf('/', delimiterIndex)) != -1)
|
||||
{
|
||||
if (currentSegmentIndex++ == index)
|
||||
{
|
||||
return new PathSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSegmentStart = delimiterIndex + 1;
|
||||
delimiterIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here we're at the end of the string. The implementation of .Count should protect us
|
||||
// from these cases.
|
||||
Debug.Assert(_path[_path.Length - 1] != '/');
|
||||
Debug.Assert(currentSegmentIndex == index);
|
||||
|
||||
return new PathSegment(_path, currentSegmentStart, _path.Length - currentSegmentStart);
|
||||
}
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
IEnumerator<PathSegment> IEnumerable<PathSegment>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<PathSegment>
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
private int _index;
|
||||
private int _length;
|
||||
|
||||
public Enumerator(PathTokenizer tokenizer)
|
||||
{
|
||||
_path = tokenizer._path;
|
||||
|
||||
_index = -1;
|
||||
_length = -1;
|
||||
}
|
||||
|
||||
public PathSegment Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return new PathSegment(_path, _index, _length);
|
||||
}
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_path == null || _path.Length <= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_index == -1)
|
||||
{
|
||||
// Skip the first `/`.
|
||||
_index = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip to the end of the previous segment + the separator.
|
||||
_index += _length + 1;
|
||||
}
|
||||
|
||||
if (_index >= _path.Length)
|
||||
{
|
||||
// We're at the end
|
||||
return false;
|
||||
}
|
||||
|
||||
var delimiterIndex = _path.IndexOf('/', _index);
|
||||
if (delimiterIndex != -1)
|
||||
{
|
||||
_length = delimiterIndex - _index;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We might have some trailing text after the last separator.
|
||||
if (_path[_path.Length - 1] == '/')
|
||||
{
|
||||
// If the last char is a '/' then it's just a trailing slash, we don't have another segment.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_length = _path.Length - _index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_index = -1;
|
||||
_length = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Routing.Template
|
||||
{
|
||||
|
|
@ -36,18 +38,12 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
|
||||
public RouteTemplate Template { get; private set; }
|
||||
|
||||
public IDictionary<string, object> Match(string requestPath)
|
||||
public IDictionary<string, object> Match(PathString path)
|
||||
{
|
||||
if (requestPath == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestPath));
|
||||
}
|
||||
|
||||
var requestSegments = requestPath.Split(Delimiters);
|
||||
|
||||
var values = new RouteValueDictionary();
|
||||
|
||||
for (var i = 0; i < requestSegments.Length; i++)
|
||||
var requestSegments = new PathTokenizer(path);
|
||||
for (var i = 0; i < requestSegments.Count; i++)
|
||||
{
|
||||
var routeSegment = Template.Segments.Count > i ? Template.Segments[i] : null;
|
||||
var requestSegment = requestSegments[i];
|
||||
|
|
@ -67,7 +63,7 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
var part = routeSegment.Parts[0];
|
||||
if (part.IsLiteral)
|
||||
{
|
||||
if (!string.Equals(part.Text, requestSegment, StringComparison.OrdinalIgnoreCase))
|
||||
if (!requestSegment.Equals(part.Text))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -78,7 +74,7 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
|
||||
if (part.IsCatchAll)
|
||||
{
|
||||
var captured = string.Join(SeparatorString, requestSegments, i, requestSegments.Length - i);
|
||||
var captured = requestSegment.GetRemainingPath();
|
||||
if (captured.Length > 0)
|
||||
{
|
||||
values.Add(part.Name, captured);
|
||||
|
|
@ -99,7 +95,7 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
{
|
||||
if (requestSegment.Length > 0)
|
||||
{
|
||||
values.Add(part.Name, requestSegment);
|
||||
values.Add(part.Name, requestSegment.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -124,14 +120,14 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!MatchComplexSegment(routeSegment, requestSegment, Defaults, values))
|
||||
if (!MatchComplexSegment(routeSegment, requestSegment.ToString(), Defaults, values))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = requestSegments.Length; i < Template.Segments.Count; i++)
|
||||
for (var i = requestSegments.Count; i < Template.Segments.Count; i++)
|
||||
{
|
||||
// We've matched the request path so far, but still have remaining route segments. These need
|
||||
// to be all single-part parameter segments with default values or else they won't match.
|
||||
|
|
@ -179,10 +175,11 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
return values;
|
||||
}
|
||||
|
||||
private bool MatchComplexSegment(TemplateSegment routeSegment,
|
||||
string requestSegment,
|
||||
IReadOnlyDictionary<string, object> defaults,
|
||||
RouteValueDictionary values)
|
||||
private bool MatchComplexSegment(
|
||||
TemplateSegment routeSegment,
|
||||
string requestSegment,
|
||||
IReadOnlyDictionary<string, object> defaults,
|
||||
RouteValueDictionary values)
|
||||
{
|
||||
var indexOfLastSegment = routeSegment.Parts.Count - 1;
|
||||
|
||||
|
|
@ -225,11 +222,12 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
}
|
||||
}
|
||||
|
||||
private bool MatchComplexSegmentCore(TemplateSegment routeSegment,
|
||||
string requestSegment,
|
||||
IReadOnlyDictionary<string, object> defaults,
|
||||
RouteValueDictionary values,
|
||||
int indexOfLastSegmentUsed)
|
||||
private bool MatchComplexSegmentCore(
|
||||
TemplateSegment routeSegment,
|
||||
string requestSegment,
|
||||
IReadOnlyDictionary<string, object> defaults,
|
||||
RouteValueDictionary values,
|
||||
int indexOfLastSegmentUsed)
|
||||
{
|
||||
Debug.Assert(routeSegment != null);
|
||||
Debug.Assert(routeSegment.Parts.Count > 1);
|
||||
|
|
@ -269,9 +267,10 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
return false;
|
||||
}
|
||||
|
||||
var indexOfLiteral = requestSegment.LastIndexOf(part.Text,
|
||||
startIndex,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
var indexOfLiteral = requestSegment.LastIndexOf(
|
||||
part.Text,
|
||||
startIndex,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
if (indexOfLiteral == -1)
|
||||
{
|
||||
// If we couldn't find this literal index, this segment cannot match
|
||||
|
|
|
|||
|
|
@ -115,13 +115,7 @@ namespace Microsoft.AspNet.Routing.Template
|
|||
|
||||
EnsureLoggers(context.HttpContext);
|
||||
|
||||
var requestPath = context.HttpContext.Request.Path.Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
|
||||
{
|
||||
requestPath = requestPath.Substring(1);
|
||||
}
|
||||
|
||||
var requestPath = context.HttpContext.Request.Path;
|
||||
var values = _matcher.Match(requestPath);
|
||||
|
||||
if (values == null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Http;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Routing.Internal
|
||||
{
|
||||
public class PathTokenizerTest
|
||||
{
|
||||
public static TheoryData<string, PathSegment[]> TokenizationData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<string, PathSegment[]>
|
||||
{
|
||||
{ string.Empty, new PathSegment[] { } },
|
||||
{ "/", new PathSegment[] { } },
|
||||
{ "//", new PathSegment[] { new PathSegment("//", 1, 0) } },
|
||||
{
|
||||
"///",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("///", 1, 0),
|
||||
new PathSegment("///", 2, 0),
|
||||
}
|
||||
},
|
||||
{
|
||||
"////",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("////", 1, 0),
|
||||
new PathSegment("////", 2, 0),
|
||||
new PathSegment("////", 3, 0),
|
||||
}
|
||||
},
|
||||
{ "/zero", new PathSegment[] { new PathSegment("/zero", 1, 4) } },
|
||||
{ "/zero/", new PathSegment[] { new PathSegment("/zero/", 1, 4) } },
|
||||
{
|
||||
"/zero/one",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("/zero/one", 1, 4),
|
||||
new PathSegment("/zero/one", 6, 3),
|
||||
}
|
||||
},
|
||||
{
|
||||
"/zero/one/",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("/zero/one/", 1, 4),
|
||||
new PathSegment("/zero/one/", 6, 3),
|
||||
}
|
||||
},
|
||||
{
|
||||
"/zero/one/two",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("/zero/one/two", 1, 4),
|
||||
new PathSegment("/zero/one/two", 6, 3),
|
||||
new PathSegment("/zero/one/two", 10, 3),
|
||||
}
|
||||
},
|
||||
{
|
||||
"/zero/one/two/",
|
||||
new PathSegment[]
|
||||
{
|
||||
new PathSegment("/zero/one/two/", 1, 4),
|
||||
new PathSegment("/zero/one/two/", 6, 3),
|
||||
new PathSegment("/zero/one/two/", 10, 3),
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TokenizationData))]
|
||||
public void PathTokenizer_Count(string path, PathSegment[] expectedSegments)
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = new PathTokenizer(new PathString(path));
|
||||
|
||||
// Act
|
||||
var count = tokenizer.Count;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedSegments.Length, count);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TokenizationData))]
|
||||
public void PathTokenizer_Indexer(string path, PathSegment[] expectedSegments)
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = new PathTokenizer(new PathString(path));
|
||||
|
||||
// Act & Assert
|
||||
for (var i = 0; i < expectedSegments.Length; i++)
|
||||
{
|
||||
Assert.Equal(expectedSegments[i], tokenizer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TokenizationData))]
|
||||
public void PathTokenizer_Enumerator(string path, PathSegment[] expectedSegments)
|
||||
{
|
||||
// Arrange
|
||||
var tokenizer = new PathTokenizer(new PathString(path));
|
||||
|
||||
// Act & Assert
|
||||
Assert.Equal<PathSegment>(expectedSegments, tokenizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Xunit;
|
||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{controller}/{action}/{id}");
|
||||
|
||||
// Act
|
||||
var match = matcher.Match("Bank/DoAction/123");
|
||||
var match = matcher.Match("/Bank/DoAction/123");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(match);
|
||||
|
|
@ -35,7 +36,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{controller}/{action}/{id}");
|
||||
|
||||
// Act
|
||||
var match = matcher.Match("Bank/DoAction");
|
||||
var match = matcher.Match("/Bank/DoAction");
|
||||
|
||||
// Assert
|
||||
Assert.Null(match);
|
||||
|
|
@ -48,7 +49,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{controller}/{action}/{id}", new { id = "default id" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("Bank/DoAction");
|
||||
var rd = matcher.Match("/Bank/DoAction");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Bank", rd["controller"]);
|
||||
|
|
@ -63,7 +64,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{controller}/{action}/{id}", new { id = "default id" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("Bank");
|
||||
var rd = matcher.Match("/Bank");
|
||||
|
||||
// Assert
|
||||
Assert.Null(rd);
|
||||
|
|
@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/{p1}/bar/{p2}", new { p2 = "default p2" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/111/bar/222");
|
||||
var rd = matcher.Match("/moo/111/bar/222");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("111", rd["p1"]);
|
||||
|
|
@ -90,7 +91,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/{p1}/bar/{p2}", new { p2 = "default p2" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/111/bar/");
|
||||
var rd = matcher.Match("/moo/111/bar/");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("111", rd["p1"]);
|
||||
|
|
@ -98,10 +99,10 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}", "123-456-7890")] // ssn
|
||||
[InlineData(@"{p1:regex(^\w+\@\w+\.\w+)}", "asd@assds.com")] // email
|
||||
[InlineData(@"{p1:regex(([}}])\w+)}", "}sda")] // Not balanced }
|
||||
[InlineData(@"{p1:regex(([{{)])\w+)}", "})sda")] // Not balanced {
|
||||
[InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}", "/123-456-7890")] // ssn
|
||||
[InlineData(@"{p1:regex(^\w+\@\w+\.\w+)}", "/asd@assds.com")] // email
|
||||
[InlineData(@"{p1:regex(([}}])\w+)}", "/}sda")] // Not balanced }
|
||||
[InlineData(@"{p1:regex(([{{)])\w+)}", "/})sda")] // Not balanced {
|
||||
public void MatchRoute_RegularExpression_Valid(
|
||||
string template,
|
||||
string path)
|
||||
|
|
@ -117,19 +118,19 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/foo.bar", "foo", "bar")]
|
||||
[InlineData("moo/{p1?}", "moo/foo", "foo", null)]
|
||||
[InlineData("moo/{p1?}", "moo", null, null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/foo", "foo", null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/foo..bar", "foo.", "bar")]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/foo.moo.bar", "foo.moo", "bar")]
|
||||
[InlineData("moo/{p1}.{p2}", "moo/foo.bar", "foo", "bar")]
|
||||
[InlineData("moo/foo.{p1}.{p2?}", "moo/foo.moo.bar", "moo", "bar")]
|
||||
[InlineData("moo/foo.{p1}.{p2?}", "moo/foo.moo", "moo", null)]
|
||||
[InlineData("moo/.{p2?}", "moo/.foo", null, "foo")]
|
||||
[InlineData("moo/.{p2?}", "moo", null, null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/....", "..", ".")]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/.bar", ".bar", null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/foo.bar", "foo", "bar")]
|
||||
[InlineData("moo/{p1?}", "/moo/foo", "foo", null)]
|
||||
[InlineData("moo/{p1?}", "/moo", null, null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/foo", "foo", null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/foo..bar", "foo.", "bar")]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/foo.moo.bar", "foo.moo", "bar")]
|
||||
[InlineData("moo/{p1}.{p2}", "/moo/foo.bar", "foo", "bar")]
|
||||
[InlineData("moo/foo.{p1}.{p2?}", "/moo/foo.moo.bar", "moo", "bar")]
|
||||
[InlineData("moo/foo.{p1}.{p2?}", "/moo/foo.moo", "moo", null)]
|
||||
[InlineData("moo/.{p2?}", "/moo/.foo", null, "foo")]
|
||||
[InlineData("moo/.{p2?}", "/moo", null, null)]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/....", "..", ".")]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/.bar", ".bar", null)]
|
||||
public void MatchRoute_OptionalParameter_FollowedByPeriod_Valid(
|
||||
string template,
|
||||
string path,
|
||||
|
|
@ -154,13 +155,13 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "moo/foo.moo.bar", "foo", "moo", "bar")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "moo/foo.moo", "foo", "moo", null)]
|
||||
[InlineData("moo/{p1}.{p2}.{p3}.{p4?}", "moo/foo.moo.bar", "foo", "moo", "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "foo.moo/bar", "foo", "moo", "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "foo/bar", "foo", null, "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", ".foo/bar", ".foo", null, "bar")]
|
||||
[InlineData("{p1}/{p2}/{p3?}", "foo/bar/baz", "foo", "bar", "baz")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "/moo/foo.moo.bar", "foo", "moo", "bar")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "/moo/foo.moo", "foo", "moo", null)]
|
||||
[InlineData("moo/{p1}.{p2}.{p3}.{p4?}", "/moo/foo.moo.bar", "foo", "moo", "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "/foo.moo/bar", "foo", "moo", "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "/foo/bar", "foo", null, "bar")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "/.foo/bar", ".foo", null, "bar")]
|
||||
[InlineData("{p1}/{p2}/{p3?}", "/foo/bar/baz", "foo", "bar", "baz")]
|
||||
public void MatchRoute_OptionalParameter_FollowedByPeriod_3Parameters_Valid(
|
||||
string template,
|
||||
string path,
|
||||
|
|
@ -189,18 +190,18 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/foo.")]
|
||||
[InlineData("moo/{p1}.{p2?}", "moo/.")]
|
||||
[InlineData("moo/{p1}.{p2}", "foo.")]
|
||||
[InlineData("moo/{p1}.{p2}", "foo")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "moo/foo.moo.")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "moo/bar.foo.moo")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "moo/kungfoo.moo.bar")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "moo/kungfoo.moo")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "moo/foo")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "foo./bar")]
|
||||
[InlineData("moo/.{p2?}", "moo/.")]
|
||||
[InlineData("{p1}.{p2}/{p3}", ".foo/bar")]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/foo.")]
|
||||
[InlineData("moo/{p1}.{p2?}", "/moo/.")]
|
||||
[InlineData("moo/{p1}.{p2}", "/foo.")]
|
||||
[InlineData("moo/{p1}.{p2}", "/foo")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "/moo/foo.moo.")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "/moo/bar.foo.moo")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "/moo/kungfoo.moo.bar")]
|
||||
[InlineData("moo/foo.{p2}.{p3?}", "/moo/kungfoo.moo")]
|
||||
[InlineData("moo/{p1}.{p2}.{p3?}", "/moo/foo")]
|
||||
[InlineData("{p1}.{p2?}/{p3}", "/foo./bar")]
|
||||
[InlineData("moo/.{p2?}", "/moo/.")]
|
||||
[InlineData("{p1}.{p2}/{p3}", "/.foo/bar")]
|
||||
public void MatchRoute_OptionalParameter_FollowedByPeriod_Invalid(string template, string path)
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -220,7 +221,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/bar");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar");
|
||||
var rd = matcher.Match("/moo/bar");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -234,7 +235,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/bars");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar");
|
||||
var rd = matcher.Match("/moo/bar");
|
||||
|
||||
// Assert
|
||||
Assert.Null(rd);
|
||||
|
|
@ -247,7 +248,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/bar");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar/");
|
||||
var rd = matcher.Match("/moo/bar/");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -261,7 +262,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("moo/bar/");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar");
|
||||
var rd = matcher.Match("/moo/bar");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -275,7 +276,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{p2}/");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar");
|
||||
var rd = matcher.Match("/moo/bar");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -290,7 +291,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{p2}/baz");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar/boo");
|
||||
var rd = matcher.Match("/moo/bar/boo");
|
||||
|
||||
// Assert
|
||||
Assert.Null(rd);
|
||||
|
|
@ -303,7 +304,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("moo/bar");
|
||||
var rd = matcher.Match("/moo/bar");
|
||||
|
||||
// Assert
|
||||
Assert.Null(rd);
|
||||
|
|
@ -316,21 +317,21 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("DEFAULT.ASPX");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("default.aspx");
|
||||
var rd = matcher.Match("/default.aspx");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{prefix}x{suffix}", "xxxxxxxxxx")]
|
||||
[InlineData("{prefix}xyz{suffix}", "xxxxyzxyzxxxxxxyz")]
|
||||
[InlineData("{prefix}xyz{suffix}", "abcxxxxyzxyzxxxxxxyzxx")]
|
||||
[InlineData("{prefix}xyz{suffix}", "xyzxyzxyzxyzxyz")]
|
||||
[InlineData("{prefix}xyz{suffix}", "xyzxyzxyzxyzxyz1")]
|
||||
[InlineData("{prefix}xyz{suffix}", "xyzxyzxyz")]
|
||||
[InlineData("{prefix}aa{suffix}", "aaaaa")]
|
||||
[InlineData("{prefix}aaa{suffix}", "aaaaa")]
|
||||
[InlineData("{prefix}x{suffix}", "/xxxxxxxxxx")]
|
||||
[InlineData("{prefix}xyz{suffix}", "/xxxxyzxyzxxxxxxyz")]
|
||||
[InlineData("{prefix}xyz{suffix}", "/abcxxxxyzxyzxxxxxxyzxx")]
|
||||
[InlineData("{prefix}xyz{suffix}", "/xyzxyzxyzxyzxyz")]
|
||||
[InlineData("{prefix}xyz{suffix}", "/xyzxyzxyzxyzxyz1")]
|
||||
[InlineData("{prefix}xyz{suffix}", "/xyzxyzxyz")]
|
||||
[InlineData("{prefix}aa{suffix}", "/aaaaa")]
|
||||
[InlineData("{prefix}aaa{suffix}", "/aaaaa")]
|
||||
public void VerifyRouteMatchesWithContext(string template, string path)
|
||||
{
|
||||
var matcher = CreateMatcher(template);
|
||||
|
|
@ -349,7 +350,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{p2}", new { p2 = (string)null, foo = "bar" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1");
|
||||
var rd = matcher.Match("/v1");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -368,7 +369,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
new { controller = "blog", action = "showpost", m = (string)null, d = (string)null });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("date/2007/08");
|
||||
var rd = matcher.Match("/date/2007/08");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -385,7 +386,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}-{region}",
|
||||
"language/en-US",
|
||||
"/language/en-US",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en", region = "US" }));
|
||||
}
|
||||
|
|
@ -395,7 +396,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}-{region}a",
|
||||
"language/en-USa",
|
||||
"/language/en-USa",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en", region = "US" }));
|
||||
}
|
||||
|
|
@ -405,7 +406,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}-{region}",
|
||||
"language/aen-US",
|
||||
"/language/aen-US",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en", region = "US" }));
|
||||
}
|
||||
|
|
@ -415,7 +416,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}-{region}a",
|
||||
"language/aen-USa",
|
||||
"/language/aen-USa",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en", region = "US" }));
|
||||
}
|
||||
|
|
@ -425,7 +426,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}-{region}a",
|
||||
"language/a-USa",
|
||||
"/language/a-USa",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -435,7 +436,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}-{region}a",
|
||||
"language/aen-a",
|
||||
"/language/aen-a",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -445,7 +446,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}",
|
||||
"language/en",
|
||||
"/language/en",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en" }));
|
||||
}
|
||||
|
|
@ -455,7 +456,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}",
|
||||
"language/",
|
||||
"/language/",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -465,7 +466,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}",
|
||||
"language",
|
||||
"/language",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -475,7 +476,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}-",
|
||||
"language/en-",
|
||||
"/language/en-",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en" }));
|
||||
}
|
||||
|
|
@ -485,7 +486,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}",
|
||||
"language/aen",
|
||||
"/language/aen",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en" }));
|
||||
}
|
||||
|
|
@ -495,7 +496,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/a{lang}a",
|
||||
"language/aena",
|
||||
"/language/aena",
|
||||
null,
|
||||
new RouteValueDictionary(new { lang = "en" }));
|
||||
}
|
||||
|
|
@ -505,7 +506,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{controller}.mvc/{action}/{id}",
|
||||
"home.mvc/index",
|
||||
"/home.mvc/index",
|
||||
new RouteValueDictionary(new { action = "Index", id = (string)null }),
|
||||
new RouteValueDictionary(new { controller = "home", action = "index", id = (string)null }));
|
||||
}
|
||||
|
|
@ -515,7 +516,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"language/{lang}-{region}",
|
||||
"language/-",
|
||||
"/language/-",
|
||||
new RouteValueDictionary(new { lang = "xx", region = "yy" }),
|
||||
null);
|
||||
}
|
||||
|
|
@ -525,7 +526,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{Controller}..mvc/{id}/{Param1}",
|
||||
"Home..mvc/123/p1",
|
||||
"/Home..mvc/123/p1",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", id = "123", Param1 = "p1" }));
|
||||
}
|
||||
|
|
@ -535,7 +536,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{Controller}.mvc/../{action}",
|
||||
"Home.mvc/../index",
|
||||
"/Home.mvc/../index",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", action = "index" }));
|
||||
}
|
||||
|
|
@ -545,7 +546,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{Controller}.mvc/.../{action}",
|
||||
"Home.mvc/.../index",
|
||||
"/Home.mvc/.../index",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", action = "index" }));
|
||||
}
|
||||
|
|
@ -555,7 +556,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{Controller}.mvc/../../../{action}",
|
||||
"Home.mvc/../../../index",
|
||||
"/Home.mvc/../../../index",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", action = "index" }));
|
||||
}
|
||||
|
|
@ -565,7 +566,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{Controller}.mvc!/{action}",
|
||||
"Home.mvc!/index",
|
||||
"/Home.mvc!/index",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", action = "index" }));
|
||||
}
|
||||
|
|
@ -575,7 +576,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"../{Controller}.mvc",
|
||||
"../Home.mvc",
|
||||
"/../Home.mvc",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home" }));
|
||||
}
|
||||
|
|
@ -585,7 +586,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
@"\{Controller}.mvc",
|
||||
@"\Home.mvc",
|
||||
@"/\Home.mvc",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home" }));
|
||||
}
|
||||
|
|
@ -595,7 +596,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
@"{Controller}.mvc\{id}\{Param1}",
|
||||
@"Home.mvc\123\p1",
|
||||
@"/Home.mvc\123\p1",
|
||||
null,
|
||||
new RouteValueDictionary(new { Controller = "Home", id = "123", Param1 = "p1" }));
|
||||
}
|
||||
|
|
@ -605,7 +606,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
@"(Controller).mvc",
|
||||
@"(Controller).mvc",
|
||||
@"/(Controller).mvc",
|
||||
null,
|
||||
new RouteValueDictionary());
|
||||
}
|
||||
|
|
@ -615,7 +616,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
@"Controller.mvc/ ",
|
||||
@"Controller.mvc/ ",
|
||||
@"/Controller.mvc/ ",
|
||||
null,
|
||||
new RouteValueDictionary());
|
||||
}
|
||||
|
|
@ -625,7 +626,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
@"Controller.mvc ",
|
||||
@"Controller.mvc ",
|
||||
@"/Controller.mvc ",
|
||||
null,
|
||||
new RouteValueDictionary());
|
||||
}
|
||||
|
|
@ -636,7 +637,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
// DevDiv Bugs 189892: UrlRouting: Catch all parameter cannot capture url segments that contain the "."
|
||||
RunTest(
|
||||
"Home/ShowPilot/{missionId}/{*name}",
|
||||
"Home/ShowPilot/777/12345./foobar",
|
||||
"/Home/ShowPilot/777/12345./foobar",
|
||||
new RouteValueDictionary(new
|
||||
{
|
||||
controller = "Home",
|
||||
|
|
@ -654,7 +655,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{*p2}");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1/v2/v3");
|
||||
var rd = matcher.Match("/v1/v2/v3");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -670,7 +671,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{*p2}");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1/");
|
||||
var rd = matcher.Match("/v1/");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -686,7 +687,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{*p2}");
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1");
|
||||
var rd = matcher.Match("/v1");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -702,7 +703,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{*p2}", new { p2 = "catchall" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1");
|
||||
var rd = matcher.Match("/v1");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -718,7 +719,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
var matcher = CreateMatcher("{p1}/{*p2}", new { p2 = "catchall" });
|
||||
|
||||
// Act
|
||||
var rd = matcher.Match("v1/hello/whatever");
|
||||
var rd = matcher.Match("/v1/hello/whatever");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(rd);
|
||||
|
|
@ -733,7 +734,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
// DevDiv Bugs 191180: UrlRouting: Wrong template getting matched if a url segment is a substring of the requested url
|
||||
RunTest(
|
||||
"foo",
|
||||
"fooBAR",
|
||||
"/fooBAR",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -744,7 +745,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
// DevDiv Bugs 191180: UrlRouting: Wrong template getting matched if a url segment is a substring of the requested url
|
||||
RunTest(
|
||||
"foo",
|
||||
"BARfoo",
|
||||
"/BARfoo",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -755,7 +756,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
// DevDiv Bugs 191180: UrlRouting: Wrong template getting matched if a url segment is a substring of the requested url
|
||||
RunTest(
|
||||
"foo",
|
||||
"BARfooBAR",
|
||||
"/BARfooBAR",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
|
@ -766,7 +767,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
// DevDiv Bugs 191180: UrlRouting: Wrong template getting matched if a url segment is a substring of the requested url
|
||||
RunTest(
|
||||
"foo",
|
||||
"foo",
|
||||
"/foo",
|
||||
null,
|
||||
new RouteValueDictionary());
|
||||
}
|
||||
|
|
@ -776,7 +777,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"foo/{ }/{.!$%}/{dynamic.data}/{op.tional}",
|
||||
"foo/space/weird/orderid",
|
||||
"/foo/space/weird/orderid",
|
||||
new RouteValueDictionary() { { " ", "not a space" }, { "op.tional", "default value" }, { "ran!dom", "va@lue" } },
|
||||
new RouteValueDictionary() { { " ", "space" }, { ".!$%", "weird" }, { "dynamic.data", "orderid" }, { "op.tional", "default value" }, { "ran!dom", "va@lue" } });
|
||||
}
|
||||
|
|
@ -786,7 +787,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{controller}/{language}-{locale}",
|
||||
"foo",
|
||||
"/foo",
|
||||
new RouteValueDictionary(new { language = "en", locale = "US" }),
|
||||
null);
|
||||
}
|
||||
|
|
@ -796,7 +797,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{controller}/{language}-{locale}",
|
||||
"foo/xx-",
|
||||
"/foo/xx-",
|
||||
new RouteValueDictionary(new { language = "en", locale = "US" }),
|
||||
null);
|
||||
}
|
||||
|
|
@ -806,7 +807,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{controller}/{language}-{locale}",
|
||||
"foo/-yy",
|
||||
"/foo/-yy",
|
||||
new RouteValueDictionary(new { language = "en", locale = "US" }),
|
||||
null);
|
||||
}
|
||||
|
|
@ -816,7 +817,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
RunTest(
|
||||
"{controller}/{language}-{locale}",
|
||||
"foo/xx-yy",
|
||||
"/foo/xx-yy",
|
||||
new RouteValueDictionary(new { language = "en", locale = "US" }),
|
||||
new RouteValueDictionary { { "language", "xx" }, { "locale", "yy" }, { "controller", "foo" } });
|
||||
}
|
||||
|
|
@ -826,7 +827,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
// Arrange
|
||||
var route = CreateMatcher("{controller}/{action?}");
|
||||
var url = "Home/Index";
|
||||
var url = "/Home/Index";
|
||||
|
||||
// Act
|
||||
var match = route.Match(url);
|
||||
|
|
@ -843,7 +844,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
// Arrange
|
||||
var route = CreateMatcher("{controller}/{action?}");
|
||||
var url = "Home";
|
||||
var url = "/Home";
|
||||
|
||||
// Act
|
||||
var match = route.Match(url);
|
||||
|
|
@ -891,7 +892,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
{
|
||||
// Arrange
|
||||
var route = CreateMatcher("{controller}/{action?}/{id?}");
|
||||
var url = "Home/Index";
|
||||
var url = "/Home/Index";
|
||||
|
||||
// Act
|
||||
var match = route.Match(url);
|
||||
|
|
@ -923,7 +924,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
|||
defaults ?? new Dictionary<string, object>());
|
||||
|
||||
// Act
|
||||
var match = matcher.Match(path);
|
||||
var match = matcher.Match(new PathString(path));
|
||||
|
||||
// Assert
|
||||
if (expected == null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue