Fix #248 Add HttpMethodRouteConstraint

Constraint code ported from WebAPI2. Tests are new.

Also a bunch of misc cleanup for constraints.
- Move IRouteConstraint to abstractions
- Fix namespace of a constraint
- Some general style cleanup
- use RouteValueDictionary in the public API
This commit is contained in:
Ryan Nowak 2015-12-11 17:02:06 -08:00
parent 9a178b9d38
commit 604fc6bb54
32 changed files with 266 additions and 84 deletions

View File

@ -1,13 +1,13 @@
// 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.Collections.Generic;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Routing
{
/// <summary>
/// Defines the contract that a class must implement in order to check whether a URL parameter value is valid for a constraint.
/// Defines the contract that a class must implement in order to check whether a URL parameter
/// value is valid for a constraint.
/// </summary>
public interface IRouteConstraint
{
@ -18,13 +18,16 @@ namespace Microsoft.AspNet.Routing
/// <param name="route">The router that this constraint belongs to.</param>
/// <param name="routeKey">The name of the parameter that is being checked.</param>
/// <param name="values">A dictionary that contains the parameters for the URL.</param>
/// <param name="routeDirection">An object that indicates whether the constraint check is being performed when an incoming request is being handled or when a URL is being generated.</param>
/// <param name="routeDirection">
/// An object that indicates whether the constraint check is being performed
/// when an incoming request is being handled or when a URL is being generated.
/// </param>
/// <returns><c>true</c> if the URL parameter contains a valid value; otherwise, <c>false</c>.</returns>
bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection);
}
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -51,7 +50,7 @@ namespace Microsoft.AspNet.Routing.Constraints
bool result;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return Boolean.TryParse(valueString, out result);
return bool.TryParse(valueString, out result);
}
return false;

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Routing
namespace Microsoft.AspNet.Routing.Constraints
{
/// <summary>
/// Constrains a route by several child constraints.
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Routing
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -24,7 +23,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -51,7 +50,7 @@ namespace Microsoft.AspNet.Routing.Constraints
decimal result;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return Decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out result);
return decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out result);
}
return false;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -51,11 +50,13 @@ namespace Microsoft.AspNet.Routing.Constraints
double result;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return Double.TryParse(valueString,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out result);
return double.TryParse(
valueString,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out result);
}
return false;
}
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -51,10 +50,11 @@ namespace Microsoft.AspNet.Routing.Constraints
float result;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return Single.TryParse(valueString,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out result);
return float.TryParse(
valueString,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out result);
}
return false;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -20,7 +19,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -0,0 +1,96 @@
// 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.Generic;
using System.Linq;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Routing.Constraints
{
/// <summary>
/// Constrains the HTTP method of request or a route.
/// </summary>
public class HttpMethodConstraint : IRouteConstraint
{
/// <summary>
/// Creates a new <see cref="HttpMethodConstraint"/> that accepts the HTTP methods specified
/// by <paramref name="allowedMethods"/>.
/// </summary>
/// <param name="allowedMethods">The allowed HTTP methods.</param>
public HttpMethodConstraint(params string[] allowedMethods)
{
if (allowedMethods == null)
{
throw new ArgumentNullException(nameof(allowedMethods));
}
AllowedMethods = new List<string>(allowedMethods);
}
/// <summary>
/// Gets the HTTP methods allowed by the constraint.
/// </summary>
public IList<string> AllowedMethods { get; }
/// <inheritdoc />
public virtual bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
{
throw new ArgumentNullException(nameof(httpContext));
}
if (route == null)
{
throw new ArgumentNullException(nameof(route));
}
if (routeKey == null)
{
throw new ArgumentNullException(nameof(routeKey));
}
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}
switch (routeDirection)
{
case RouteDirection.IncomingRequest:
return AllowedMethods.Contains(httpContext.Request.Method, StringComparer.OrdinalIgnoreCase);
case RouteDirection.UrlGeneration:
// We need to see if the user specified the HTTP method explicitly. Consider these two routes:
//
// a) Route: template = "/{foo}", Constraints = { httpMethod = new HttpMethodConstraint("GET") }
// b) Route: template = "/{foo}", Constraints = { httpMethod = new HttpMethodConstraint("POST") }
//
// A user might know ahead of time that a URI he/she is generating might be used with a particular HTTP
// method. If a URI will be used for an HTTP POST but we match on (a) while generating the URI, then
// the HTTP GET-specific route will be used for URI generation, which might have undesired behavior.
//
// To prevent this, a user might call GetVirtualPath(..., { httpMethod = "POST" }) to
// signal that he is generating a URI that will be used for an HTTP POST, so he wants the URI
// generation to be performed by the (b) route instead of the (a) route, consistent with what would
// happen on incoming requests.
object obj;
if (!values.TryGetValue(routeKey, out obj))
{
return true;
}
return AllowedMethods.Contains(Convert.ToString(obj), StringComparer.OrdinalIgnoreCase);
default:
throw new ArgumentOutOfRangeException(nameof(routeDirection));
}
}
}
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -51,7 +50,7 @@ namespace Microsoft.AspNet.Routing.Constraints
int result;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return Int32.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
return int.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
}
return false;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -63,19 +62,19 @@ namespace Microsoft.AspNet.Routing.Constraints
/// <summary>
/// Gets the minimum length allowed for the route parameter.
/// </summary>
public int MinLength { get; private set; }
public int MinLength { get; }
/// <summary>
/// Gets the maximum length allowed for the route parameter.
/// </summary>
public int MaxLength { get; private set; }
public int MaxLength { get; }
/// <inheritdoc />
public bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -31,14 +30,14 @@ namespace Microsoft.AspNet.Routing.Constraints
/// <summary>
/// Gets the maximum length allowed for the route parameter.
/// </summary>
public int MaxLength { get; private set; }
public int MaxLength { get; }
/// <inheritdoc />
public bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -32,7 +31,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -60,7 +59,7 @@ namespace Microsoft.AspNet.Routing.Constraints
{
long longValue;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
if (long.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
{
return longValue <= Max;
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -38,7 +37,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -25,14 +24,14 @@ namespace Microsoft.AspNet.Routing.Constraints
/// <summary>
/// Gets the minimum allowed value of the route parameter.
/// </summary>
public long Min { get; private set; }
public long Min { get; }
/// <inheritdoc />
public bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)
@ -60,7 +59,7 @@ namespace Microsoft.AspNet.Routing.Constraints
{
long longValue;
var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
if (long.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
{
return longValue >= Min;
}

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Routing.Constraints
@ -28,7 +27,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -46,7 +45,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -1,8 +1,6 @@
// 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.Constraints
{
/// <summary>

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.AspNet.Http;
@ -42,7 +41,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNet.Http;
@ -22,7 +21,7 @@ namespace Microsoft.AspNet.Routing.Constraints
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (httpContext == null)

View File

@ -12,7 +12,7 @@ namespace Microsoft.AspNet.Routing
{
public static bool Match(
IDictionary<string, IRouteConstraint> constraints,
IDictionary<string, object> routeValues,
RouteValueDictionary routeValues,
HttpContext httpContext,
IRouter route,
RouteDirection routeDirection,

View File

@ -220,11 +220,12 @@ namespace Microsoft.AspNet.Routing
_expectedKey = expectedKey;
}
public bool Match(HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteDirection routeDirection)
public bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (_expectedKey != null)
{
@ -237,11 +238,12 @@ namespace Microsoft.AspNet.Routing
private class FailConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteDirection routeDirection)
public bool Match(
HttpContext httpContext,
IRouter route,
string routeKey,
RouteValueDictionary values,
RouteDirection routeDirection)
{
return false;
}

View File

@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Routing.Constraints;
using Moq;
using Xunit;
@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Routing.Tests
It.IsAny<HttpContext>(),
It.IsAny<IRouter>(),
It.IsAny<string>(),
It.IsAny<Dictionary<string, object>>(),
It.IsAny<RouteValueDictionary>(),
It.IsAny<RouteDirection>());
private static Mock<IRouteConstraint> MockConstraintWithResult(bool result)

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Routing.Tests
}
var parameterName = "fake";
var values = new Dictionary<string, object>() { { parameterName, value } };
var values = new RouteValueDictionary() { { parameterName, value } };
var routeDirection = RouteDirection.IncomingRequest;
return constraint.Match(context.Object, route, parameterName, values, routeDirection);
}

View File

@ -0,0 +1,94 @@
// 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.Internal;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Routing.Constraints
{
public class HttpMethodRouteConstraintTests
{
[Theory]
[InlineData("GET")]
[InlineData("PosT")]
public void HttpMethodRouteConstraint_IncomingRequest_AcceptsAllowedMethods(string httpMethod)
{
// Arrange
var constraint = new HttpMethodConstraint("GET", "post");
var httpContext = new DefaultHttpContext();
httpContext.Request.Method = httpMethod;
var route = Mock.Of<IRouter>();
var values = new RouteValueDictionary(new { });
// Act
var result = constraint.Match(httpContext, route, "httpMethod", values, RouteDirection.IncomingRequest);
// Assert
Assert.True(result);
}
[Theory]
[InlineData("OPTIONS")]
[InlineData("SomeRandomThing")]
public void HttpMethodRouteConstraint_IncomingRequest_RejectsOtherMethods(string httpMethod)
{
// Arrange
var constraint = new HttpMethodConstraint("GET", "post");
var httpContext = new DefaultHttpContext();
httpContext.Request.Method = httpMethod;
var route = Mock.Of<IRouter>();
var values = new RouteValueDictionary(new { });
// Act
var result = constraint.Match(httpContext, route, "httpMethod", values, RouteDirection.IncomingRequest);
// Assert
Assert.False(result);
}
[Theory]
[InlineData("GET")]
[InlineData("PosT")]
public void HttpMethodRouteConstraint_UrlGeneration_AcceptsAllowedMethods(string httpMethod)
{
// Arrange
var constraint = new HttpMethodConstraint("GET", "post");
var httpContext = new DefaultHttpContext();
var route = Mock.Of<IRouter>();
var values = new RouteValueDictionary(new { httpMethod = httpMethod });
// Act
var result = constraint.Match(httpContext, route, "httpMethod", values, RouteDirection.UrlGeneration);
// Assert
Assert.True(result);
}
[Theory]
[InlineData("OPTIONS")]
[InlineData("SomeRandomThing")]
public void HttpMethodRouteConstraint_UrlGeneration_RejectsOtherMethods(string httpMethod)
{
// Arrange
var constraint = new HttpMethodConstraint("GET", "post");
var httpContext = new DefaultHttpContext();
var route = Mock.Of<IRouter>();
var values = new RouteValueDictionary(new { httpMethod = httpMethod });
// Act
var result = constraint.Match(httpContext, route, "httpMethod", values, RouteDirection.UrlGeneration);
// Assert
Assert.False(result);
}
}
}

View File

@ -343,7 +343,7 @@ namespace Microsoft.AspNet.Routing.Tests
public bool Match(HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
return true;
@ -361,7 +361,7 @@ namespace Microsoft.AspNet.Routing.Tests
public bool Match(HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
return true;

View File

@ -982,7 +982,7 @@ namespace Microsoft.AspNet.Routing.Tests
public bool Match(HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
throw new NotImplementedException();

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Routing.Tests
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
throw new NotImplementedException();

View File

@ -832,11 +832,14 @@ namespace Microsoft.AspNet.Routing
var context = CreateVirtualPathContext(new { p1 = "hello", p2 = "1234" });
var target = new Mock<IRouteConstraint>();
target.Setup(e => e.Match(It.IsAny<HttpContext>(),
It.IsAny<IRouter>(),
It.IsAny<string>(),
It.IsAny<IDictionary<string, object>>(),
It.IsAny<RouteDirection>()))
target
.Setup(
e => e.Match(
It.IsAny<HttpContext>(),
It.IsAny<IRouter>(),
It.IsAny<string>(),
It.IsAny<RouteValueDictionary>(),
It.IsAny<RouteDirection>()))
.Returns(true)
.Verifiable();
@ -1594,7 +1597,7 @@ namespace Microsoft.AspNet.Routing
HttpContext httpContext,
IRouter route,
string routeKey,
IDictionary<string, object> values,
RouteValueDictionary values,
RouteDirection routeDirection)
{
Values = new RouteValueDictionary(values);

View File

@ -1610,7 +1610,7 @@ namespace Microsoft.AspNet.Routing.Tree
It.IsAny<HttpContext>(),
It.IsAny<IRouter>(),
It.IsAny<string>(),
It.IsAny<IDictionary<string, object>>(),
It.IsAny<RouteValueDictionary>(),
It.IsAny<RouteDirection>()))
.Returns(true);