Simplify link generation code
- Removes ProvidedValues and IsBound - Removes best-effort link generation - simplify code where possible - lots of test simplification
This commit is contained in:
parent
c911a10692
commit
b01183f023
|
|
@ -25,8 +25,6 @@ namespace RoutingSample.Web
|
||||||
|
|
||||||
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||||
{
|
{
|
||||||
// We don't really care what the values look like.
|
|
||||||
context.IsBound = true;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.AspNet.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing
|
namespace Microsoft.AspNet.Routing
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A context for virtual path generation operations.
|
||||||
|
/// </summary>
|
||||||
public class VirtualPathContext
|
public class VirtualPathContext
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="VirtualPathContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="Http.HttpContext"/> associated with the current request.</param>
|
||||||
|
/// <param name="ambientValues">The set of route values associated with the current request.</param>
|
||||||
|
/// <param name="values">The set of new values provided for virtual path generation.</param>
|
||||||
public VirtualPathContext(
|
public VirtualPathContext(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
RouteValueDictionary ambientValues,
|
RouteValueDictionary ambientValues,
|
||||||
|
|
@ -16,28 +24,43 @@ namespace Microsoft.AspNet.Routing
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="VirtualPathContext"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">The <see cref="Http.HttpContext"/> associated with the current request.</param>
|
||||||
|
/// <param name="ambientValues">The set of route values associated with the current request.</param>
|
||||||
|
/// <param name="values">The set of new values provided for virtual path generation.</param>
|
||||||
|
/// <param name="routeName">The name of the route to use for virtual path generation.</param>
|
||||||
public VirtualPathContext(
|
public VirtualPathContext(
|
||||||
HttpContext context,
|
HttpContext httpContext,
|
||||||
RouteValueDictionary ambientValues,
|
RouteValueDictionary ambientValues,
|
||||||
RouteValueDictionary values,
|
RouteValueDictionary values,
|
||||||
string routeName)
|
string routeName)
|
||||||
{
|
{
|
||||||
Context = context;
|
HttpContext = httpContext;
|
||||||
AmbientValues = ambientValues;
|
AmbientValues = ambientValues;
|
||||||
Values = values;
|
Values = values;
|
||||||
RouteName = routeName;
|
RouteName = routeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RouteName { get; }
|
/// <summary>
|
||||||
|
/// Gets the set of route values associated with the current request.
|
||||||
public IDictionary<string, object> ProvidedValues { get; set; }
|
/// </summary>
|
||||||
|
|
||||||
public RouteValueDictionary AmbientValues { get; }
|
public RouteValueDictionary AmbientValues { get; }
|
||||||
|
|
||||||
public HttpContext Context { get; }
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Http.HttpContext"/> associated with the current request.
|
||||||
|
/// </summary>
|
||||||
|
public HttpContext HttpContext { get; }
|
||||||
|
|
||||||
public bool IsBound { get; set; }
|
/// <summary>
|
||||||
|
/// Gets the name of the route to use for virtual path generation.
|
||||||
|
/// </summary>
|
||||||
|
public string RouteName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the set of new values provided for virtual path generation.
|
||||||
|
/// </summary>
|
||||||
public RouteValueDictionary Values { get; }
|
public RouteValueDictionary Values { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,123 +86,58 @@ namespace Microsoft.AspNet.Routing
|
||||||
|
|
||||||
public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
|
public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||||
{
|
{
|
||||||
EnsureOptions(context.Context);
|
EnsureOptions(context.HttpContext);
|
||||||
|
|
||||||
// If we're using Best-Effort link generation then it means that we'll first look for a route where
|
|
||||||
// the route values are validated (context.IsBound == true). If we can't find a match like that, then
|
|
||||||
// we'll return the path from the first route to return one.
|
|
||||||
var useBestEffort = _options.UseBestEffortLinkGeneration;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(context.RouteName))
|
if (!string.IsNullOrEmpty(context.RouteName))
|
||||||
{
|
{
|
||||||
var isValidated = false;
|
VirtualPathData namedRoutePathData = null;
|
||||||
VirtualPathData bestPathData = null;
|
|
||||||
INamedRouter matchedNamedRoute;
|
INamedRouter matchedNamedRoute;
|
||||||
if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute))
|
if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute))
|
||||||
{
|
{
|
||||||
bestPathData = matchedNamedRoute.GetVirtualPath(context);
|
namedRoutePathData = matchedNamedRoute.GetVirtualPath(context);
|
||||||
isValidated = context.IsBound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here and context.IsBound == true, then we know we have a match, we want to keep
|
var pathData = GetVirtualPath(context, _unnamedRoutes);
|
||||||
// iterating to see if we have multiple matches.
|
|
||||||
foreach (var unnamedRoute in _unnamedRoutes)
|
// If the named route and one of the unnamed routes also matches, then we have an ambiguity.
|
||||||
|
if (namedRoutePathData != null && pathData != null)
|
||||||
{
|
{
|
||||||
// reset because we're sharing the context
|
var message = Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName);
|
||||||
context.IsBound = false;
|
throw new InvalidOperationException(message);
|
||||||
|
|
||||||
var pathData = unnamedRoute.GetVirtualPath(context);
|
|
||||||
if (pathData == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestPathData != null)
|
|
||||||
{
|
|
||||||
// There was already a previous route which matched the name.
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName));
|
|
||||||
}
|
|
||||||
else if (context.IsBound)
|
|
||||||
{
|
|
||||||
// This is the first 'validated' match that we've found.
|
|
||||||
bestPathData = pathData;
|
|
||||||
isValidated = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Assert(bestPathData == null);
|
|
||||||
|
|
||||||
// This is the first 'unvalidated' match that we've found.
|
|
||||||
bestPathData = pathData;
|
|
||||||
isValidated = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidated || useBestEffort)
|
return NormalizeVirtualPath(namedRoutePathData ?? pathData);
|
||||||
{
|
|
||||||
context.IsBound = isValidated;
|
|
||||||
|
|
||||||
if (bestPathData != null)
|
|
||||||
{
|
|
||||||
bestPathData = new VirtualPathData(
|
|
||||||
bestPathData.Router,
|
|
||||||
NormalizeVirtualPath(bestPathData.VirtualPath),
|
|
||||||
bestPathData.DataTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bestPathData;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VirtualPathData bestPathData = null;
|
return NormalizeVirtualPath(GetVirtualPath(context, _routes));
|
||||||
for (var i = 0; i < Count; i++)
|
|
||||||
{
|
|
||||||
var route = this[i];
|
|
||||||
|
|
||||||
var pathData = route.GetVirtualPath(context);
|
|
||||||
if (pathData == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.IsBound)
|
|
||||||
{
|
|
||||||
// This route has validated route values, short circuit.
|
|
||||||
return new VirtualPathData(
|
|
||||||
pathData.Router,
|
|
||||||
NormalizeVirtualPath(pathData.VirtualPath),
|
|
||||||
pathData.DataTokens);
|
|
||||||
}
|
|
||||||
else if (bestPathData == null)
|
|
||||||
{
|
|
||||||
// The values aren't validated, but this is the best we've seen so far
|
|
||||||
bestPathData = pathData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useBestEffort)
|
|
||||||
{
|
|
||||||
return new VirtualPathData(
|
|
||||||
bestPathData.Router,
|
|
||||||
NormalizeVirtualPath(bestPathData.VirtualPath),
|
|
||||||
bestPathData.DataTokens);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathString NormalizeVirtualPath(PathString path)
|
private VirtualPathData GetVirtualPath(VirtualPathContext context, List<IRouter> routes)
|
||||||
{
|
{
|
||||||
var url = path.Value;
|
for (var i = 0; i < routes.Count; i++)
|
||||||
|
{
|
||||||
|
var route = routes[i];
|
||||||
|
|
||||||
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
if (pathData != null)
|
||||||
|
{
|
||||||
|
return pathData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VirtualPathData NormalizeVirtualPath(VirtualPathData pathData)
|
||||||
|
{
|
||||||
|
if (pathData == null)
|
||||||
|
{
|
||||||
|
return pathData;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = pathData.VirtualPath.Value;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(url) && (_options.LowercaseUrls || _options.AppendTrailingSlash))
|
if (!string.IsNullOrEmpty(url) && (_options.LowercaseUrls || _options.AppendTrailingSlash))
|
||||||
{
|
{
|
||||||
|
|
@ -229,10 +164,10 @@ namespace Microsoft.AspNet.Routing
|
||||||
// queryString will contain the delimiter ? or # as the first character, so it's safe to append.
|
// queryString will contain the delimiter ? or # as the first character, so it's safe to append.
|
||||||
url = urlWithoutQueryString + queryString;
|
url = urlWithoutQueryString + queryString;
|
||||||
|
|
||||||
return new PathString(url);
|
return new VirtualPathData(pathData.Router, url, pathData.DataTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return pathData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureOptions(HttpContext context)
|
private void EnsureOptions(HttpContext context)
|
||||||
|
|
|
||||||
|
|
@ -69,13 +69,5 @@ namespace Microsoft.AspNet.Routing
|
||||||
{"required", typeof(RequiredRouteConstraint) },
|
{"required", typeof(RequiredRouteConstraint) },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the value that enables best-effort link generation.
|
|
||||||
///
|
|
||||||
/// If enabled, link generation will use allow link generation to succeed when the set of values provided
|
|
||||||
/// cannot be validated.
|
|
||||||
/// </summary>
|
|
||||||
public bool UseBestEffortLinkGeneration { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,21 +179,19 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureLoggers(context.Context);
|
EnsureLoggers(context.HttpContext);
|
||||||
if (!RouteConstraintMatcher.Match(Constraints,
|
if (!RouteConstraintMatcher.Match(
|
||||||
values.CombinedValues,
|
Constraints,
|
||||||
context.Context,
|
values.CombinedValues,
|
||||||
this,
|
context.HttpContext,
|
||||||
RouteDirection.UrlGeneration,
|
this,
|
||||||
_constraintLogger))
|
RouteDirection.UrlGeneration,
|
||||||
|
_constraintLogger))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that the target can accept these values.
|
var pathData = _target.GetVirtualPath(context);
|
||||||
var childContext = CreateChildVirtualPathContext(context, values.AcceptedValues);
|
|
||||||
|
|
||||||
var pathData = _target.GetVirtualPath(childContext);
|
|
||||||
if (pathData != null)
|
if (pathData != null)
|
||||||
{
|
{
|
||||||
// If the target generates a value then that can short circuit.
|
// If the target generates a value then that can short circuit.
|
||||||
|
|
@ -219,43 +217,9 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.IsBound = childContext.IsBound;
|
|
||||||
|
|
||||||
return pathData;
|
return pathData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VirtualPathContext CreateChildVirtualPathContext(
|
|
||||||
VirtualPathContext context,
|
|
||||||
IDictionary<string, object> acceptedValues)
|
|
||||||
{
|
|
||||||
// We want to build the set of values that would be provided if this route were to generated
|
|
||||||
// a link and then immediately match it. This includes all the accepted parameter values, and
|
|
||||||
// the defaults. Accepted values that would go in the query string aren't included.
|
|
||||||
var providedValues = new RouteValueDictionary();
|
|
||||||
|
|
||||||
foreach (var parameter in _parsedTemplate.Parameters)
|
|
||||||
{
|
|
||||||
object value;
|
|
||||||
if (acceptedValues.TryGetValue(parameter.Name, out value))
|
|
||||||
{
|
|
||||||
providedValues.Add(parameter.Name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kvp in _defaults)
|
|
||||||
{
|
|
||||||
if (!providedValues.ContainsKey(kvp.Key))
|
|
||||||
{
|
|
||||||
providedValues.Add(kvp.Key, kvp.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new VirtualPathContext(context.Context, context.AmbientValues, context.Values)
|
|
||||||
{
|
|
||||||
ProvidedValues = providedValues,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IReadOnlyDictionary<string, IRouteConstraint> GetConstraints(
|
private static IReadOnlyDictionary<string, IRouteConstraint> GetConstraints(
|
||||||
IInlineConstraintResolver inlineConstraintResolver,
|
IInlineConstraintResolver inlineConstraintResolver,
|
||||||
string template,
|
string template,
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var path = GenerateVirtualPath(context, match.Entry);
|
var path = GenerateVirtualPath(context, match.Entry);
|
||||||
if (path != null)
|
if (path != null)
|
||||||
{
|
{
|
||||||
context.IsBound = true;
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +381,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var path = GenerateVirtualPath(context, entry);
|
var path = GenerateVirtualPath(context, entry);
|
||||||
if (path != null)
|
if (path != null)
|
||||||
{
|
{
|
||||||
context.IsBound = true;
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +428,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var matched = RouteConstraintMatcher.Match(
|
var matched = RouteConstraintMatcher.Match(
|
||||||
entry.Constraints,
|
entry.Constraints,
|
||||||
bindingResult.CombinedValues,
|
bindingResult.CombinedValues,
|
||||||
context.Context,
|
context.HttpContext,
|
||||||
this,
|
this,
|
||||||
RouteDirection.UrlGeneration,
|
RouteDirection.UrlGeneration,
|
||||||
_constraintLogger);
|
_constraintLogger);
|
||||||
|
|
@ -441,30 +439,13 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These values are used to signal to the next route what we would produce if we round-tripped
|
var pathData = _next.GetVirtualPath(context);
|
||||||
// (generate a link and then parse). In MVC the 'next route' is typically the MvcRouteHandler.
|
|
||||||
var providedValues = new Dictionary<string, object>(
|
|
||||||
bindingResult.AcceptedValues,
|
|
||||||
StringComparer.OrdinalIgnoreCase);
|
|
||||||
providedValues.Add(RouteGroupKey, entry.RouteGroup);
|
|
||||||
|
|
||||||
var childContext = new VirtualPathContext(context.Context, context.AmbientValues, context.Values)
|
|
||||||
{
|
|
||||||
ProvidedValues = providedValues,
|
|
||||||
};
|
|
||||||
|
|
||||||
var pathData = _next.GetVirtualPath(childContext);
|
|
||||||
if (pathData != null)
|
if (pathData != null)
|
||||||
{
|
{
|
||||||
// If path is non-null then the target router short-circuited, we don't expect this
|
// If path is non-null then the target router short-circuited, we don't expect this
|
||||||
// in typical MVC scenarios.
|
// in typical MVC scenarios.
|
||||||
return pathData;
|
return pathData;
|
||||||
}
|
}
|
||||||
else if (!childContext.IsBound)
|
|
||||||
{
|
|
||||||
// The target router has rejected these values. We don't expect this in typical MVC scenarios.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = entry.Binder.BindValues(bindingResult.AcceptedValues);
|
var path = entry.Binder.BindValues(bindingResult.AcceptedValues);
|
||||||
if (path == null)
|
if (path == null)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ namespace Microsoft.AspNet.Routing
|
||||||
var virtualPathContext = CreateVirtualPathContext(
|
var virtualPathContext = CreateVirtualPathContext(
|
||||||
options: GetRouteOptions(
|
options: GetRouteOptions(
|
||||||
lowerCaseUrls: lowercaseUrls,
|
lowerCaseUrls: lowercaseUrls,
|
||||||
useBestEffortLinkGeneration: true,
|
|
||||||
appendTrailingSlash: appendTrailingSlash));
|
appendTrailingSlash: appendTrailingSlash));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -88,7 +87,7 @@ namespace Microsoft.AspNet.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData("DataTokensTestData")]
|
[MemberData(nameof(DataTokensTestData))]
|
||||||
public void GetVirtualPath_ReturnsDataTokens(RouteValueDictionary dataTokens, string routerName)
|
public void GetVirtualPath_ReturnsDataTokens(RouteValueDictionary dataTokens, string routerName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -286,306 +285,13 @@ namespace Microsoft.AspNet.Routing
|
||||||
innerRouteCollection.Add(namedRoute);
|
innerRouteCollection.Add(namedRoute);
|
||||||
routeCollection.Add(innerRouteCollection);
|
routeCollection.Add(innerRouteCollection);
|
||||||
|
|
||||||
var options = new RouteOptions()
|
var virtualPathContext = CreateVirtualPathContext("Ambiguous", options: new RouteOptions());
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext("Ambiguous", options: options);
|
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var ex = Assert.Throws<InvalidOperationException>(() => routeCollection.GetVirtualPath(virtualPathContext));
|
var ex = Assert.Throws<InvalidOperationException>(() => routeCollection.GetVirtualPath(virtualPathContext));
|
||||||
Assert.Equal("The supplied route name 'Ambiguous' is ambiguous and matched more than one route.", ex.Message);
|
Assert.Equal("The supplied route name 'Ambiguous' is ambiguous and matched more than one route.", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_NamedRoute_BestEffort_BestInTopCollection()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bestMatch = CreateNamedRoute("Match", accept: true, matchValue: "best");
|
|
||||||
var noMatch = CreateNamedRoute("NoMatch", accept: true, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(bestMatch);
|
|
||||||
|
|
||||||
var innerRouteCollection = new RouteCollection();
|
|
||||||
innerRouteCollection.Add(noMatch);
|
|
||||||
routeCollection.Add(innerRouteCollection);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext("Match", options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
var namedRouter = Assert.IsAssignableFrom<INamedRouter>(pathData.Router);
|
|
||||||
Assert.Equal("Match", namedRouter.Name);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_NamedRoute_BestEffort_BestMatchInNestedCollection()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bestMatch = CreateNamedRoute("NoMatch", accept: true, matchValue: "bad");
|
|
||||||
var noMatch = CreateNamedRoute("Match", accept: true, matchValue: "best");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(noMatch);
|
|
||||||
|
|
||||||
var innerRouteCollection = new RouteCollection();
|
|
||||||
innerRouteCollection.Add(bestMatch);
|
|
||||||
routeCollection.Add(innerRouteCollection);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext("Match", options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
var namedRouter = Assert.IsAssignableFrom<INamedRouter>(pathData.Router);
|
|
||||||
Assert.Equal("Match", namedRouter.Name);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_NamedRoute_BestEffort_FirstRouteWins()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var bestMatch = CreateNamedRoute("Match", accept: false, matchValue: "best");
|
|
||||||
var noMatch = CreateNamedRoute("NoMatch", accept: false, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(noMatch);
|
|
||||||
|
|
||||||
var innerRouteCollection = new RouteCollection();
|
|
||||||
innerRouteCollection.Add(bestMatch);
|
|
||||||
routeCollection.Add(innerRouteCollection);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext("Match", options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
var namedRouter = Assert.IsAssignableFrom<INamedRouter>(pathData.Router);
|
|
||||||
Assert.Equal("Match", namedRouter.Name);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_BestEffort_FirstRouteWins()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: true, matchValue: "best");
|
|
||||||
var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route3 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
routeCollection.Add(route2.Object);
|
|
||||||
routeCollection.Add(route3.Object);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route1.Object, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
// All of these should be called
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_NoBestEffort_NoMatch()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: true, matchValue: "best");
|
|
||||||
var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route3 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
routeCollection.Add(route2.Object);
|
|
||||||
routeCollection.Add(route3.Object);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var path = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Null(path);
|
|
||||||
|
|
||||||
// All of these should be called
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_BestEffort_FirstRouteWins_WithNonMatchingRoutes()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: false, matchValue: "bad");
|
|
||||||
var route2 = CreateRoute(accept: false, match: true, matchValue: "best");
|
|
||||||
var route3 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
routeCollection.Add(route2.Object);
|
|
||||||
routeCollection.Add(route3.Object);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route2.Object, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
// All of these should be called
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_BestEffort_FirstValidatedValuesWins()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route3 = CreateRoute(accept: true, match: true, matchValue: "best");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
routeCollection.Add(route2.Object);
|
|
||||||
routeCollection.Add(route3.Object);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route3.Object, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
// All of these should be called
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_BestEffort_FirstValidatedValuesWins_ShortCircuit()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route2 = CreateRoute(accept: true, match: true, matchValue: "best");
|
|
||||||
var route3 = CreateRoute(accept: true, match: true, matchValue: "bad");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
routeCollection.Add(route2.Object);
|
|
||||||
routeCollection.Add(route3.Object);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route2.Object, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Never());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_BestEffort_FirstValidatedValuesWins_Nested()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route1 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route2 = CreateRoute(accept: false, match: true, matchValue: "bad");
|
|
||||||
var route3 = CreateRoute(accept: true, match: true, matchValue: "best");
|
|
||||||
|
|
||||||
var routeCollection = new RouteCollection();
|
|
||||||
routeCollection.Add(route1.Object);
|
|
||||||
|
|
||||||
var innerRouteCollection = new RouteCollection();
|
|
||||||
innerRouteCollection.Add(route2.Object);
|
|
||||||
innerRouteCollection.Add(route3.Object);
|
|
||||||
routeCollection.Add(innerRouteCollection);
|
|
||||||
|
|
||||||
var options = new RouteOptions()
|
|
||||||
{
|
|
||||||
UseBestEffortLinkGeneration = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var virtualPathContext = CreateVirtualPathContext(options: options);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = routeCollection.GetVirtualPath(virtualPathContext);
|
|
||||||
|
|
||||||
Assert.Equal(new PathString("/best"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route3.Object, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
// All of these should be called
|
|
||||||
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Integration" tests for RouteCollection
|
// "Integration" tests for RouteCollection
|
||||||
|
|
||||||
public static IEnumerable<object[]> IntegrationTestData
|
public static IEnumerable<object[]> IntegrationTestData
|
||||||
|
|
@ -633,7 +339,7 @@ namespace Microsoft.AspNet.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData("IntegrationTestData")]
|
[MemberData(nameof(IntegrationTestData))]
|
||||||
public void GetVirtualPath_Success(
|
public void GetVirtualPath_Success(
|
||||||
string template,
|
string template,
|
||||||
RouteValueDictionary values,
|
RouteValueDictionary values,
|
||||||
|
|
@ -651,12 +357,37 @@ namespace Microsoft.AspNet.Routing
|
||||||
var pathData = routeCollection.GetVirtualPath(context);
|
var pathData = routeCollection.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.Equal(new PathString(expectedUrl), pathData.VirtualPath);
|
Assert.Equal(new PathString(expectedUrl), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetVirtualPath_NoBestEffort_NoMatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route1 = CreateRoute(accept: false, match: false, matchValue: "bad");
|
||||||
|
var route2 = CreateRoute(accept: false, match: false, matchValue: "bad");
|
||||||
|
var route3 = CreateRoute(accept: false, match: false, matchValue: "bad");
|
||||||
|
|
||||||
|
var routeCollection = new RouteCollection();
|
||||||
|
routeCollection.Add(route1.Object);
|
||||||
|
routeCollection.Add(route2.Object);
|
||||||
|
routeCollection.Add(route3.Object);
|
||||||
|
|
||||||
|
var virtualPathContext = CreateVirtualPathContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var path = routeCollection.GetVirtualPath(virtualPathContext);
|
||||||
|
|
||||||
|
Assert.Null(path);
|
||||||
|
|
||||||
|
// All of these should be called
|
||||||
|
route1.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
||||||
|
route2.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
||||||
|
route3.Verify(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
// DataTokens test data for RouterCollection.GetVirtualPath
|
// DataTokens test data for RouterCollection.GetVirtualPath
|
||||||
public static IEnumerable<object[]> DataTokensTestData
|
public static IEnumerable<object[]> DataTokensTestData
|
||||||
{
|
{
|
||||||
|
|
@ -744,7 +475,6 @@ namespace Microsoft.AspNet.Routing
|
||||||
var target = new Mock<INamedRouter>(MockBehavior.Strict);
|
var target = new Mock<INamedRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = accept && c.RouteName == name)
|
|
||||||
.Returns<VirtualPathContext>(c =>
|
.Returns<VirtualPathContext>(c =>
|
||||||
c.RouteName == name ? new VirtualPathData(target.Object, matchValue) : null)
|
c.RouteName == name ? new VirtualPathData(target.Object, matchValue) : null)
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
|
|
@ -770,7 +500,6 @@ namespace Microsoft.AspNet.Routing
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = true)
|
|
||||||
.Returns<VirtualPathContext>(rc => null);
|
.Returns<VirtualPathContext>(rc => null);
|
||||||
|
|
||||||
var resolverMock = new Mock<IInlineConstraintResolver>();
|
var resolverMock = new Mock<IInlineConstraintResolver>();
|
||||||
|
|
@ -876,7 +605,6 @@ namespace Microsoft.AspNet.Routing
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = accept)
|
|
||||||
.Returns(accept || match ? new VirtualPathData(target.Object, matchValue) : null)
|
.Returns(accept || match ? new VirtualPathData(target.Object, matchValue) : null)
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
|
|
||||||
|
|
@ -891,12 +619,10 @@ namespace Microsoft.AspNet.Routing
|
||||||
|
|
||||||
private static RouteOptions GetRouteOptions(
|
private static RouteOptions GetRouteOptions(
|
||||||
bool lowerCaseUrls = false,
|
bool lowerCaseUrls = false,
|
||||||
bool useBestEffortLinkGeneration = true,
|
|
||||||
bool appendTrailingSlash = false)
|
bool appendTrailingSlash = false)
|
||||||
{
|
{
|
||||||
var routeOptions = new RouteOptions();
|
var routeOptions = new RouteOptions();
|
||||||
routeOptions.LowercaseUrls = lowerCaseUrls;
|
routeOptions.LowercaseUrls = lowerCaseUrls;
|
||||||
routeOptions.UseBestEffortLinkGeneration = useBestEffortLinkGeneration;
|
|
||||||
routeOptions.AppendTrailingSlash = appendTrailingSlash;
|
routeOptions.AppendTrailingSlash = appendTrailingSlash;
|
||||||
|
|
||||||
return routeOptions;
|
return routeOptions;
|
||||||
|
|
|
||||||
|
|
@ -881,7 +881,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.Equal(new PathString("/Home"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/Home"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
|
@ -898,7 +897,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var path = route.GetVirtualPath(context);
|
var path = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(context.IsBound);
|
|
||||||
Assert.Null(path);
|
Assert.Null(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -913,7 +911,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = true)
|
|
||||||
.Returns(() => new VirtualPathData(target.Object, path, dataTokens));
|
.Returns(() => new VirtualPathData(target.Object, path, dataTokens));
|
||||||
|
|
||||||
var routeDataTokens =
|
var routeDataTokens =
|
||||||
|
|
@ -958,7 +955,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = true)
|
|
||||||
.Returns(() => null);
|
.Returns(() => null);
|
||||||
|
|
||||||
var route = CreateRoute(
|
var route = CreateRoute(
|
||||||
|
|
@ -998,7 +994,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(context.IsBound);
|
|
||||||
Assert.Equal(new PathString("/Home"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/Home"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
|
@ -1015,7 +1010,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.Equal(new PathString("/Home/Index"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/Home/Index"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
|
@ -1037,7 +1031,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var virtualPath = r.GetVirtualPath(context);
|
var virtualPath = r.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(context.IsBound);
|
|
||||||
Assert.Null(virtualPath);
|
Assert.Null(virtualPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1057,7 +1050,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.NotNull(pathData);
|
Assert.NotNull(pathData);
|
||||||
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
|
|
@ -1080,7 +1072,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var virtualPath = r.GetVirtualPath(context);
|
var virtualPath = r.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(context.IsBound);
|
|
||||||
Assert.Null(virtualPath);
|
Assert.Null(virtualPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1100,7 +1091,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.NotNull(pathData);
|
Assert.NotNull(pathData);
|
||||||
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
|
|
@ -1132,7 +1122,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var pathData = route.GetVirtualPath(context);
|
var pathData = route.GetVirtualPath(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.True(context.IsBound);
|
|
||||||
Assert.NotNull(pathData);
|
Assert.NotNull(pathData);
|
||||||
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/hello/1234"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
|
|
@ -1141,92 +1130,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
target.VerifyAll();
|
target.VerifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_Sends_ProvidedValues()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
VirtualPathContext childContext = null;
|
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
|
||||||
target
|
|
||||||
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(c => { childContext = c; c.IsBound = true; })
|
|
||||||
.Returns<string>(null);
|
|
||||||
|
|
||||||
var route = CreateRoute(target.Object, "{controller}/{action}");
|
|
||||||
var context = CreateVirtualPathContext(
|
|
||||||
new { action = "Store" },
|
|
||||||
new { Controller = "Home", action = "Blog" });
|
|
||||||
|
|
||||||
var expectedValues = new RouteValueDictionary(new { controller = "Home", action = "Store" });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = route.GetVirtualPath(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(new PathString("/Home/Store"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
Assert.Equal(expectedValues, childContext.ProvidedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_Sends_ProvidedValues_IncludingDefaults()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
VirtualPathContext childContext = null;
|
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
|
||||||
target
|
|
||||||
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(c => { childContext = c; c.IsBound = true; })
|
|
||||||
.Returns<string>(null);
|
|
||||||
|
|
||||||
var route = CreateRoute(target.Object, "Admin/{controller}/{action}", new { area = "Admin" });
|
|
||||||
var context = CreateVirtualPathContext(
|
|
||||||
new { action = "Store" }, new { Controller = "Home", action = "Blog" });
|
|
||||||
|
|
||||||
var expectedValues = new RouteValueDictionary(
|
|
||||||
new { controller = "Home", action = "Store", area = "Admin" });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = route.GetVirtualPath(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(new PathString("/Admin/Home/Store"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
Assert.Equal(expectedValues, childContext.ProvidedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetVirtualPath_Sends_ProvidedValues_ButNotQueryStringValues()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
VirtualPathContext childContext = null;
|
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
|
||||||
target
|
|
||||||
.Setup(r => r.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(c => { childContext = c; c.IsBound = true; })
|
|
||||||
.Returns<string>(null);
|
|
||||||
|
|
||||||
var route = CreateRoute(target.Object, "{controller}/{action}");
|
|
||||||
var context = CreateVirtualPathContext(
|
|
||||||
new { action = "Store", id = 5 }, new { Controller = "Home", action = "Blog" });
|
|
||||||
|
|
||||||
var expectedValues = new RouteValueDictionary(new { controller = "Home", action = "Store" });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = route.GetVirtualPath(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(new PathString("/Home/Store?id=5"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
Assert.Equal(expectedValues, childContext.ProvidedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any ambient values from the current request should be visible to constraint, even
|
// Any ambient values from the current request should be visible to constraint, even
|
||||||
// if they have nothing to do with the route generating a link
|
// if they have nothing to do with the route generating a link
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1930,7 +1833,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Callback<VirtualPathContext>(c => c.IsBound = handleRequest)
|
|
||||||
.Returns<VirtualPathContext>(rc => null);
|
.Returns<VirtualPathContext>(rc => null);
|
||||||
|
|
||||||
target
|
target
|
||||||
|
|
|
||||||
|
|
@ -376,22 +376,13 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GenerateLink(string firstTemplate, string secondTemplate, string expectedPath)
|
public void TreeRouter_GenerateLink(string firstTemplate, string secondTemplate, string expectedPath)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, firstTemplate);
|
|
||||||
|
|
||||||
string selectedGroup = null;
|
|
||||||
Action<VirtualPathContext> callback = ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{"url", "dingo" },
|
{"url", "dingo" },
|
||||||
{"id", 5 }
|
{"id", 5 }
|
||||||
};
|
};
|
||||||
|
|
||||||
var route = CreateAttributeRoute(callback, firstTemplate, secondTemplate);
|
var route = CreateAttributeRoute(firstTemplate, secondTemplate);
|
||||||
var context = CreateVirtualPathContext(
|
var context = CreateVirtualPathContext(
|
||||||
values: values,
|
values: values,
|
||||||
ambientValues: null);
|
ambientValues: null);
|
||||||
|
|
@ -404,7 +395,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -414,16 +404,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var firstTemplate = "template";
|
var firstTemplate = "template";
|
||||||
var secondTemplate = "template/{parameter:int=1003}";
|
var secondTemplate = "template/{parameter:int=1003}";
|
||||||
|
|
||||||
var expectedGroup = CreateRouteGroup(0, secondTemplate);
|
var route = CreateAttributeRoute(firstTemplate, secondTemplate);
|
||||||
|
|
||||||
string selectedGroup = null;
|
|
||||||
Action<VirtualPathContext> callback = ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var route = CreateAttributeRoute(callback, firstTemplate, secondTemplate);
|
|
||||||
var context = CreateVirtualPathContext(
|
var context = CreateVirtualPathContext(
|
||||||
values: null,
|
values: null,
|
||||||
ambientValues: null);
|
ambientValues: null);
|
||||||
|
|
@ -437,10 +418,8 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString($"/template"), result.VirtualPath);
|
Assert.Equal(new PathString($"/template"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
// Even though the path was /template, the group generated from was /template/{paramter:int=1003}
|
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("template/{parameter:int=5}", "template", "/template/5")]
|
[InlineData("template/{parameter:int=5}", "template", "/template/5")]
|
||||||
[InlineData("template/{parameter}", "template", "/template/5")]
|
[InlineData("template/{parameter}", "template", "/template/5")]
|
||||||
|
|
@ -450,16 +429,8 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
string secondTemplate,
|
string secondTemplate,
|
||||||
string expectedPath)
|
string expectedPath)
|
||||||
{
|
{
|
||||||
var expectedGroup = CreateRouteGroup(0, firstTemplate);
|
// Arrange
|
||||||
|
var route = CreateAttributeRoute(firstTemplate, secondTemplate);
|
||||||
string selectedGroup = null;
|
|
||||||
Action<VirtualPathContext> callback = ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var route = CreateAttributeRoute(callback, firstTemplate, secondTemplate);
|
|
||||||
var parameter = 5;
|
var parameter = 5;
|
||||||
var id = 1234;
|
var id = 1234;
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
|
|
@ -479,7 +450,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -492,16 +462,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
string expectedPath)
|
string expectedPath)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, secondTemplate);
|
var route = CreateAttributeRoute(firstTemplate, secondTemplate);
|
||||||
|
|
||||||
string selectedGroup = null;
|
|
||||||
Action<VirtualPathContext> callback = ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var route = CreateAttributeRoute(callback, firstTemplate, secondTemplate);
|
|
||||||
var parameter = 5;
|
var parameter = 5;
|
||||||
var id = 1234;
|
var id = 1234;
|
||||||
var values = new Dictionary<string, object>
|
var values = new Dictionary<string, object>
|
||||||
|
|
@ -510,7 +471,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
{ nameof(id), id }
|
{ nameof(id), id }
|
||||||
};
|
};
|
||||||
var context = CreateVirtualPathContext(
|
var context = CreateVirtualPathContext(
|
||||||
values: null,
|
values: null,
|
||||||
ambientValues: values);
|
ambientValues: values);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -521,7 +482,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
Assert.Equal(new PathString(expectedPath), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -538,18 +498,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GenerateLink_RespectsPrecedence(string firstTemplate, string secondTemplate)
|
public void TreeRouter_GenerateLink_RespectsPrecedence(string firstTemplate, string secondTemplate)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, firstTemplate);
|
|
||||||
|
|
||||||
string selectedGroup = null;
|
|
||||||
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var firstEntry = CreateGenerationEntry(firstTemplate, requiredValues: null);
|
var firstEntry = CreateGenerationEntry(firstTemplate, requiredValues: null);
|
||||||
|
|
@ -559,7 +507,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// try to generate a link, the route with a higher precedence gets tried first.
|
// try to generate a link, the route with a higher precedence gets tried first.
|
||||||
var linkGenerationEntries = new[] { secondEntry, firstEntry };
|
var linkGenerationEntries = new[] { secondEntry, firstEntry };
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingRoutes, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingRoutes, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(values: null, ambientValues: new { parameter = 5 });
|
var context = CreateVirtualPathContext(values: null, ambientValues: new { parameter = 5 });
|
||||||
|
|
||||||
|
|
@ -571,8 +519,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -591,25 +537,13 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
object parameter)
|
object parameter)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, template);
|
|
||||||
|
|
||||||
string selectedGroup = null;
|
|
||||||
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var entry = CreateGenerationEntry(template, requiredValues: null);
|
var entry = CreateGenerationEntry(template, requiredValues: null);
|
||||||
|
|
||||||
var linkGenerationEntries = new[] { entry };
|
var linkGenerationEntries = new[] { entry };
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingRoutes, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingRoutes, linkGenerationEntries);
|
||||||
|
|
||||||
VirtualPathContext context;
|
VirtualPathContext context;
|
||||||
if (parameter != null)
|
if (parameter != null)
|
||||||
|
|
@ -652,17 +586,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GenerateLink_RespectsOrderOverPrecedence(string firstTemplate, string secondTemplate)
|
public void TreeRouter_GenerateLink_RespectsOrderOverPrecedence(string firstTemplate, string secondTemplate)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var selectedGroup = CreateRouteGroup(0, secondTemplate);
|
|
||||||
|
|
||||||
string firstRouteGroupSelected = null;
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
|
|
||||||
{
|
|
||||||
firstRouteGroupSelected = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 1);
|
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 1);
|
||||||
|
|
@ -673,7 +596,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// relative order gets tried first.
|
// relative order gets tried first.
|
||||||
var linkGenerationEntries = new[] { firstRoute, secondRoute };
|
var linkGenerationEntries = new[] { firstRoute, secondRoute };
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingRoutes, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingRoutes, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(null, ambientValues: new { parameter = 5 });
|
var context = CreateVirtualPathContext(null, ambientValues: new { parameter = 5 });
|
||||||
|
|
||||||
|
|
@ -685,8 +608,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(selectedGroup, firstRouteGroupSelected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -698,17 +619,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GenerateLink_RespectsOrder(string firstTemplate, string secondTemplate)
|
public void TreeRouter_GenerateLink_RespectsOrder(string firstTemplate, string secondTemplate)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, secondTemplate);
|
|
||||||
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
string selectedGroup = null;
|
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 1);
|
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 1);
|
||||||
|
|
@ -718,7 +628,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// we try to generate a link, the route with the higher relative order gets tried first.
|
// we try to generate a link, the route with the higher relative order gets tried first.
|
||||||
var linkGenerationEntries = new[] { firstRoute, secondRoute };
|
var linkGenerationEntries = new[] { firstRoute, secondRoute };
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingRoutes, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingRoutes, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 });
|
var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 });
|
||||||
|
|
||||||
|
|
@ -730,8 +640,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -743,17 +651,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GenerateLink_EnsuresStableOrder(string firstTemplate, string secondTemplate)
|
public void TreeRouter_GenerateLink_EnsuresStableOrder(string firstTemplate, string secondTemplate)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedGroup = CreateRouteGroup(0, firstTemplate);
|
|
||||||
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
string selectedGroup = null;
|
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
|
|
||||||
{
|
|
||||||
selectedGroup = (string)ctx.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
ctx.IsBound = true;
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 0);
|
var firstRoute = CreateGenerationEntry(firstTemplate, requiredValues: null, order: 0);
|
||||||
|
|
@ -763,7 +660,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// we try to generate a link, the route with the higher template order gets tried first.
|
// we try to generate a link, the route with the higher template order gets tried first.
|
||||||
var linkGenerationEntries = new[] { secondRoute, firstRoute };
|
var linkGenerationEntries = new[] { secondRoute, firstRoute };
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingRoutes, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingRoutes, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 });
|
var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 });
|
||||||
|
|
||||||
|
|
@ -775,8 +672,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/first/5"), result.VirtualPath);
|
Assert.Equal(new PathString("/first/5"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> NamedEntriesWithDifferentTemplates
|
public static IEnumerable<object[]> NamedEntriesWithDifferentTemplates
|
||||||
|
|
@ -880,20 +775,9 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var expectedLink = new PathString(
|
var expectedLink = new PathString(
|
||||||
namedEntries.First().Template.Parameters.Any() ? "/template/5" : "/template");
|
namedEntries.First().Template.Parameters.Any() ? "/template/5" : "/template");
|
||||||
|
|
||||||
var expectedGroup = "0&" + namedEntries.First().Template.TemplateText;
|
|
||||||
string selectedGroup = null;
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(vpc =>
|
|
||||||
{
|
|
||||||
vpc.IsBound = true;
|
|
||||||
selectedGroup = (string)vpc.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingEntries, namedEntries);
|
var route = CreateAttributeRoute(matchingEntries, namedEntries);
|
||||||
|
|
||||||
var ambientValues = namedEntries.First().Template.Parameters.Any() ? new { parameter = 5 } : null;
|
var ambientValues = namedEntries.First().Template.Parameters.Any() ? new { parameter = 5 } : null;
|
||||||
|
|
||||||
|
|
@ -907,24 +791,12 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(expectedLink, result.VirtualPath);
|
Assert.Equal(expectedLink, result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedGroup, selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TreeRouter_GenerateLink_WithName()
|
public void TreeRouter_GenerateLink_WithName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string selectedGroup = null;
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(vpc =>
|
|
||||||
{
|
|
||||||
vpc.IsBound = true;
|
|
||||||
selectedGroup = (string)vpc.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
|
||||||
|
|
||||||
var namedEntry = CreateGenerationEntry("named", requiredValues: null, order: 1, name: "NamedRoute");
|
var namedEntry = CreateGenerationEntry("named", requiredValues: null, order: 1, name: "NamedRoute");
|
||||||
var unnamedEntry = CreateGenerationEntry("unnamed", requiredValues: null, order: 0);
|
var unnamedEntry = CreateGenerationEntry("unnamed", requiredValues: null, order: 0);
|
||||||
|
|
||||||
|
|
@ -934,7 +806,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
|
|
||||||
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingEntries, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingEntries, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(values: null, ambientValues: null, name: "NamedRoute");
|
var context = CreateVirtualPathContext(values: null, ambientValues: null, name: "NamedRoute");
|
||||||
|
|
||||||
|
|
@ -946,23 +818,12 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/named"), result.VirtualPath);
|
Assert.Equal(new PathString("/named"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal("1&named", selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TreeRouter_DoesNotGenerateLink_IfThereIsNoRouteForAGivenName()
|
public void TreeRouter_DoesNotGenerateLink_IfThereIsNoRouteForAGivenName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string selectedGroup = null;
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(vpc =>
|
|
||||||
{
|
|
||||||
vpc.IsBound = true;
|
|
||||||
selectedGroup = (string)vpc.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
});
|
|
||||||
|
|
||||||
var namedEntry = CreateGenerationEntry("named", requiredValues: null, order: 1, name: "NamedRoute");
|
var namedEntry = CreateGenerationEntry("named", requiredValues: null, order: 1, name: "NamedRoute");
|
||||||
|
|
||||||
// Add an unnamed entry to ensure we don't fall back to generating a link for an unnamed route.
|
// Add an unnamed entry to ensure we don't fall back to generating a link for an unnamed route.
|
||||||
|
|
@ -974,7 +835,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
|
|
||||||
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingEntries, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingEntries, linkGenerationEntries);
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(values: null, ambientValues: null, name: "NonExistingNamedRoute");
|
var context = CreateVirtualPathContext(values: null, ambientValues: null, name: "NonExistingNamedRoute");
|
||||||
|
|
||||||
|
|
@ -994,15 +855,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_DoesNotGenerateLink_IfValuesDoNotMatchNamedEntry(string template, string value)
|
public void TreeRouter_DoesNotGenerateLink_IfValuesDoNotMatchNamedEntry(string template, string value)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string selectedGroup = null;
|
|
||||||
var next = new Mock<IRouter>();
|
|
||||||
next.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
|
||||||
.Callback<VirtualPathContext>(vpc =>
|
|
||||||
{
|
|
||||||
vpc.IsBound = true;
|
|
||||||
selectedGroup = (string)vpc.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
});
|
|
||||||
|
|
||||||
var namedEntry = CreateGenerationEntry(template, requiredValues: null, order: 1, name: "NamedRoute");
|
var namedEntry = CreateGenerationEntry(template, requiredValues: null, order: 1, name: "NamedRoute");
|
||||||
|
|
||||||
// Add an unnamed entry to ensure we don't fall back to generating a link for an unnamed route.
|
// Add an unnamed entry to ensure we don't fall back to generating a link for an unnamed route.
|
||||||
|
|
@ -1014,7 +866,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
|
|
||||||
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingEntries = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next.Object, matchingEntries, linkGenerationEntries);
|
var route = CreateAttributeRoute(matchingEntries, linkGenerationEntries);
|
||||||
|
|
||||||
var ambientValues = value == null ? null : new { parameter = value };
|
var ambientValues = value == null ? null : new { parameter = value };
|
||||||
|
|
||||||
|
|
@ -1035,14 +887,9 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public void TreeRouter_GeneratesLink_IfValuesMatchNamedEntry(string template, string value)
|
public void TreeRouter_GeneratesLink_IfValuesMatchNamedEntry(string template, string value)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string selectedGroup = null;
|
|
||||||
var next = new Mock<IRouter>();
|
var next = new Mock<IRouter>();
|
||||||
next.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
next
|
||||||
.Callback<VirtualPathContext>(vpc =>
|
.Setup(s => s.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
{
|
|
||||||
vpc.IsBound = true;
|
|
||||||
selectedGroup = (string)vpc.ProvidedValues[TreeRouter.RouteGroupKey];
|
|
||||||
})
|
|
||||||
.Returns((VirtualPathData)null);
|
.Returns((VirtualPathData)null);
|
||||||
|
|
||||||
var namedEntry = CreateGenerationEntry(template, requiredValues: null, order: 1, name: "NamedRoute");
|
var namedEntry = CreateGenerationEntry(template, requiredValues: null, order: 1, name: "NamedRoute");
|
||||||
|
|
@ -1070,11 +917,9 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
Assert.Equal(new PathString("/template/5"), result.VirtualPath);
|
||||||
Assert.Same(route, result.Router);
|
Assert.Same(route, result.Router);
|
||||||
Assert.Empty(result.DataTokens);
|
Assert.Empty(result.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(string.Format("1&{0}", template), selectedGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TreeRouter_GenerateLink_NoRequiredValues()
|
public void TreeRouter_GenerateLink_NoRequiredValues()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|
@ -1174,14 +1019,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
"api/{area}/dosomething/{controller}/{action}",
|
"api/{area}/dosomething/{controller}/{action}",
|
||||||
new { action = "Index", controller = "Store", area = "AwesomeCo" });
|
new { action = "Index", controller = "Store", area = "AwesomeCo" });
|
||||||
|
|
||||||
var expectedValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "area", "AwesomeCo" },
|
|
||||||
{ "controller", "Store" },
|
|
||||||
{ "action", "Index" },
|
|
||||||
{ TreeRouter.RouteGroupKey, entry.RouteGroup },
|
|
||||||
};
|
|
||||||
|
|
||||||
var next = new StubRouter();
|
var next = new StubRouter();
|
||||||
var route = CreateAttributeRoute(next, entry);
|
var route = CreateAttributeRoute(next, entry);
|
||||||
|
|
||||||
|
|
@ -1197,8 +1034,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/api/AwesomeCo/dosomething/Store/Index"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/api/AwesomeCo/dosomething/Store/Index"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedValues, next.GenerationContext.ProvidedValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1226,13 +1061,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// Arrange
|
// Arrange
|
||||||
var entry = CreateGenerationEntry("api/Store/{action}/{id:int}", new { action = "Index", controller = "Store" });
|
var entry = CreateGenerationEntry("api/Store/{action}/{id:int}", new { action = "Index", controller = "Store" });
|
||||||
|
|
||||||
var expectedValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "action", "Index" },
|
|
||||||
{ "id", 5 },
|
|
||||||
{ TreeRouter.RouteGroupKey, entry.RouteGroup },
|
|
||||||
};
|
|
||||||
|
|
||||||
var next = new StubRouter();
|
var next = new StubRouter();
|
||||||
var route = CreateAttributeRoute(next, entry);
|
var route = CreateAttributeRoute(next, entry);
|
||||||
|
|
||||||
|
|
@ -1246,8 +1074,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Equal(new PathString("/api/Store/Index/5"), pathData.VirtualPath);
|
Assert.Equal(new PathString("/api/Store/Index/5"), pathData.VirtualPath);
|
||||||
Assert.Same(route, pathData.Router);
|
Assert.Same(route, pathData.Router);
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
|
||||||
Assert.Equal(expectedValues, next.GenerationContext.ProvidedValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1257,12 +1083,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
var entry = CreateGenerationEntry("api/Store/{action}/{id:int}", new { action = "Index", controller = "Store" });
|
var entry = CreateGenerationEntry("api/Store/{action}/{id:int}", new { action = "Index", controller = "Store" });
|
||||||
var route = CreateAttributeRoute(entry);
|
var route = CreateAttributeRoute(entry);
|
||||||
|
|
||||||
var expectedValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "id", "5" },
|
|
||||||
{ TreeRouter.RouteGroupKey, entry.RouteGroup },
|
|
||||||
};
|
|
||||||
|
|
||||||
var next = new StubRouter();
|
var next = new StubRouter();
|
||||||
var context = CreateVirtualPathContext(new { action = "Index", controller = "Store", id = "heyyyy" });
|
var context = CreateVirtualPathContext(new { action = "Index", controller = "Store", id = "heyyyy" });
|
||||||
|
|
||||||
|
|
@ -1311,29 +1131,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void TreeRouter_GenerateLink_ForwardsRouteGroup()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var entry = CreateGenerationEntry("api/Store", new { action = "Index", controller = "Store" });
|
|
||||||
|
|
||||||
var expectedValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ TreeRouter.RouteGroupKey, entry.RouteGroup },
|
|
||||||
};
|
|
||||||
|
|
||||||
var next = new StubRouter();
|
|
||||||
var route = CreateAttributeRoute(next, entry);
|
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(new { action = "Index", controller = "Store" });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var path = route.GetVirtualPath(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(expectedValues, next.GenerationContext.ProvidedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TreeRouter_GenerateLink_RejectedByFirstRoute()
|
public void TreeRouter_GenerateLink_RejectedByFirstRoute()
|
||||||
{
|
{
|
||||||
|
|
@ -1355,41 +1152,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void TreeRouter_GenerateLink_RejectedByHandler()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var entry1 = CreateGenerationEntry("api/Store", new { action = "Edit", controller = "Store" });
|
|
||||||
var entry2 = CreateGenerationEntry("api2/{controller}", new { action = "Edit", controller = "Store" });
|
|
||||||
|
|
||||||
var next = new StubRouter();
|
|
||||||
|
|
||||||
var callCount = 0;
|
|
||||||
next.GenerationDelegate = (VirtualPathContext c) =>
|
|
||||||
{
|
|
||||||
// Reject entry 1.
|
|
||||||
callCount++;
|
|
||||||
return !c.ProvidedValues.Contains(new KeyValuePair<string, object>(
|
|
||||||
TreeRouter.RouteGroupKey,
|
|
||||||
entry1.RouteGroup));
|
|
||||||
};
|
|
||||||
|
|
||||||
var route = CreateAttributeRoute(next, entry1, entry2);
|
|
||||||
|
|
||||||
var context = CreateVirtualPathContext(new { action = "Edit", controller = "Store" });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var pathData = route.GetVirtualPath(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(pathData);
|
|
||||||
Assert.Equal(new PathString("/api2/Store"), pathData.VirtualPath);
|
|
||||||
Assert.Same(route, pathData.Router);
|
|
||||||
Assert.Empty(pathData.DataTokens);
|
|
||||||
|
|
||||||
Assert.Equal(2, callCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TreeRouter_GenerateLink_ToArea()
|
public void TreeRouter_GenerateLink_ToArea()
|
||||||
{
|
{
|
||||||
|
|
@ -1509,7 +1271,7 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
// values
|
// values
|
||||||
new object[]
|
new object[]
|
||||||
{
|
{
|
||||||
"Test/{val1}/{val2}.{val3?}",
|
"Test/{val1}/{val2}.{val3?}",
|
||||||
new {val1 = "someval1", val2 = "someval2", val3 = "someval3a"},
|
new {val1 = "someval1", val2 = "someval2", val3 = "someval3a"},
|
||||||
new {val3 = "someval3v"},
|
new {val3 = "someval3v"},
|
||||||
"/Test/someval1/someval2.someval3v",
|
"/Test/someval1/someval2.someval3v",
|
||||||
|
|
@ -1527,18 +1289,18 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
null,
|
null,
|
||||||
new {val1 = "someval1", val2 = "someval2" },
|
new {val1 = "someval1", val2 = "someval2" },
|
||||||
"/Test/someval1/someval2",
|
"/Test/someval1/someval2",
|
||||||
},
|
},
|
||||||
new object[]
|
new object[]
|
||||||
{
|
{
|
||||||
"Test/{val1}.{val2}.{val3}.{val4?}",
|
"Test/{val1}.{val2}.{val3}.{val4?}",
|
||||||
new {val1 = "someval1", val2 = "someval2" },
|
new {val1 = "someval1", val2 = "someval2" },
|
||||||
new {val4 = "someval4", val3 = "someval3" },
|
new {val4 = "someval4", val3 = "someval3" },
|
||||||
"/Test/someval1.someval2.someval3.someval4",
|
"/Test/someval1.someval2.someval3.someval4",
|
||||||
},
|
},
|
||||||
new object[]
|
new object[]
|
||||||
{
|
{
|
||||||
"Test/{val1}.{val2}.{val3}.{val4?}",
|
"Test/{val1}.{val2}.{val3}.{val4?}",
|
||||||
new {val1 = "someval1", val2 = "someval2" },
|
new {val1 = "someval1", val2 = "someval2" },
|
||||||
new {val3 = "someval3" },
|
new {val3 = "someval3" },
|
||||||
"/Test/someval1.someval2.someval3",
|
"/Test/someval1.someval2.someval3",
|
||||||
},
|
},
|
||||||
|
|
@ -1931,6 +1693,13 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
Enumerable.Empty<TreeRouteLinkGenerationEntry>());
|
Enumerable.Empty<TreeRouteLinkGenerationEntry>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TreeRouter CreateAttributeRoute(
|
||||||
|
IEnumerable<TreeRouteMatchingEntry> matchingEntries,
|
||||||
|
IEnumerable<TreeRouteLinkGenerationEntry> generationEntries)
|
||||||
|
{
|
||||||
|
return CreateAttributeRoute(new StubRouter(), matchingEntries, generationEntries);
|
||||||
|
}
|
||||||
|
|
||||||
private static TreeRouter CreateAttributeRoute(
|
private static TreeRouter CreateAttributeRoute(
|
||||||
IRouter next,
|
IRouter next,
|
||||||
IEnumerable<TreeRouteMatchingEntry> matchingEntries,
|
IEnumerable<TreeRouteMatchingEntry> matchingEntries,
|
||||||
|
|
@ -1952,13 +1721,13 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TreeRouter CreateAttributeRoute(
|
private static TreeRouter CreateAttributeRoute(
|
||||||
Action<VirtualPathContext> virtualPathCallback,
|
|
||||||
string firstTemplate,
|
string firstTemplate,
|
||||||
string secondTemplate)
|
string secondTemplate)
|
||||||
{
|
{
|
||||||
var next = new Mock<IRouter>();
|
var next = new Mock<IRouter>();
|
||||||
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(virtualPathCallback)
|
next
|
||||||
.Returns((VirtualPathData)null);
|
.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
|
.Returns((VirtualPathData)null);
|
||||||
|
|
||||||
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
var matchingRoutes = Enumerable.Empty<TreeRouteMatchingEntry>();
|
||||||
var firstEntry = CreateGenerationEntry(firstTemplate, requiredValues: null);
|
var firstEntry = CreateGenerationEntry(firstTemplate, requiredValues: null);
|
||||||
|
|
@ -2014,8 +1783,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
{
|
{
|
||||||
public VirtualPathContext GenerationContext { get; set; }
|
public VirtualPathContext GenerationContext { get; set; }
|
||||||
|
|
||||||
public Func<VirtualPathContext, bool> GenerationDelegate { get; set; }
|
|
||||||
|
|
||||||
public RouteContext MatchingContext { get; set; }
|
public RouteContext MatchingContext { get; set; }
|
||||||
|
|
||||||
public Func<RouteContext, bool> MatchingDelegate { get; set; }
|
public Func<RouteContext, bool> MatchingDelegate { get; set; }
|
||||||
|
|
@ -2023,16 +1790,6 @@ namespace Microsoft.AspNet.Routing.Tree
|
||||||
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||||
{
|
{
|
||||||
GenerationContext = context;
|
GenerationContext = context;
|
||||||
|
|
||||||
if (GenerationDelegate == null)
|
|
||||||
{
|
|
||||||
context.IsBound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.IsBound = GenerationDelegate(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue