Improve error for RRV substitution case
Fixes: #14789 Users can hit this error case when using a route parameter that has a special meaning in MVC, in attribute routing with a route constraint. This will cause us to fail while expanding the route pattern, because the canonical value associated with the parameter won't satisfy the constraint. TLDR: don't do that. Using MVC's reserved parameter names for application-level concerns will always cause bugs. This was a case where you'd fail with a totally unactionable error message. Updating it to reflect the proper root cause and our guidance to fix it.
This commit is contained in:
parent
84496d3c95
commit
f3074d92fd
|
|
@ -132,7 +132,14 @@ namespace Microsoft.AspNetCore.Mvc.Routing
|
|||
var updatedRoutePattern = _routePatternTransformer.SubstituteRequiredValues(resolvedRoutePattern, resolvedRouteValues);
|
||||
if (updatedRoutePattern == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to update route pattern with required values.");
|
||||
// This kind of thing can happen when a route pattern uses a *reserved* route value such as `action`.
|
||||
// See: https://github.com/aspnet/AspNetCore/issues/14789
|
||||
var formattedRouteKeys = string.Join(", ", resolvedRouteValues.Keys.Select(k => $"'{k}'"));
|
||||
throw new InvalidOperationException(
|
||||
$"Failed to update the route pattern '{resolvedRoutePattern.RawText}' with required route values. " +
|
||||
$"This can occur when the route pattern contains parameters with reserved names such as: {formattedRouteKeys} " +
|
||||
$"and also uses route constraints such as '{{action:int}}'. " +
|
||||
$"To fix this error, choose a different parmaeter name.");
|
||||
}
|
||||
|
||||
var builder = new RouteEndpointBuilder(_requestDelegate, updatedRoutePattern, action.AttributeRouteInfo.Order)
|
||||
|
|
|
|||
|
|
@ -208,6 +208,22 @@ namespace Microsoft.AspNetCore.Mvc.Routing
|
|||
Assert.Empty(endpoints);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddEndpoints_AttributeRouted_ContainsParameterUsingReservedNameWithConstraint_ExceptionThrown()
|
||||
{
|
||||
// Arrange
|
||||
var values = new { controller = "TestController", action = "TestAction", page = (string)null };
|
||||
var action = CreateActionDescriptor(values, "Products/{action:int}");
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => CreateAttributeRoutedEndpoint(action));
|
||||
Assert.Equal(
|
||||
"Failed to update the route pattern 'Products/{action:int}' with required route values. " +
|
||||
"This can occur when the route pattern contains parameters with reserved names such as: 'controller', 'action', 'page' and also uses route constraints such as '{action:int}'. " +
|
||||
"To fix this error, choose a different parmaeter name.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddEndpoints_AttributeRouted_ContainsParameterWithNullRequiredRouteValue_EndpointCreated()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue