[Fixes #4991] Misleading MissingMethodException message for incorrect routes

This commit is contained in:
Kiran Challa 2016-07-19 09:43:30 -07:00
parent 0bb2c3c2f7
commit a4ec3bb24a
3 changed files with 61 additions and 17 deletions

View File

@ -94,14 +94,24 @@ namespace Microsoft.AspNetCore.Mvc.Internal
defaults.Add(kvp.Key, kvp.Value); defaults.Add(kvp.Key, kvp.Value);
} }
// We use the `NullRouter` as the route handler because we don't need to do anything for link try
// generations. The TreeRouter does it all for us. {
builder.MapOutbound( // We use the `NullRouter` as the route handler because we don't need to do anything for link
NullRouter.Instance, // generations. The TreeRouter does it all for us.
routeInfo.RouteTemplate, builder.MapOutbound(
defaults, NullRouter.Instance,
routeInfo.RouteName, routeInfo.RouteTemplate,
routeInfo.Order); defaults,
routeInfo.RouteName,
routeInfo.Order);
}
catch (RouteCreationException routeCreationException)
{
throw new RouteCreationException(
"An error occurred while adding a route to the route builder. " +
$"Route name '{routeInfo.RouteName}' and template '{routeInfo.RouteTemplate.TemplateText}'.",
routeCreationException);
}
} }
// We're creating one AttributeRouteMatchingEntry per group, so we need to identify the distinct set of // We're creating one AttributeRouteMatchingEntry per group, so we need to identify the distinct set of
@ -113,7 +123,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var handler = _handlerFactory(group.ToArray()); var handler = _handlerFactory(group.ToArray());
// Note that because we only support 'inline' defaults, each routeInfo group also has the same // Note that because we only support 'inline' defaults, each routeInfo group also has the same
// set of defaults. // set of defaults.
// //
// We then inject the route group as a default for the matcher so it gets passed back to MVC // We then inject the route group as a default for the matcher so it gets passed back to MVC
// for use in action selection. // for use in action selection.
@ -167,7 +177,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
e.ErrorMessage))); e.ErrorMessage)));
var message = Resources.FormatAttributeRoute_AggregateErrorMessage(Environment.NewLine, allErrors); var message = Resources.FormatAttributeRoute_AggregateErrorMessage(Environment.NewLine, allErrors);
throw new InvalidOperationException(message); throw new RouteCreationException(message);
} }
return routeInfos; return routeInfos;
@ -227,7 +237,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
public ActionDescriptor ActionDescriptor { get; set; } public ActionDescriptor ActionDescriptor { get; set; }
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
public int Order { get; set; } public int Order { get; set; }
public string RouteName { get; set; } public string RouteName { get; set; }

View File

@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.NotNull(context.Handler); Assert.NotNull(context.Handler);
Assert.Equal("5", context.RouteData.Values["key2"]); Assert.Equal("5", context.RouteData.Values["key2"]);
Assert.Same(actions[1], selected); Assert.Same(actions[1], selected);
// Arrange 2 - remove the action and update the collection // Arrange 2 - remove the action and update the collection
selected = null; selected = null;
actions.RemoveAt(1); actions.RemoveAt(1);
@ -511,6 +511,40 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}); });
} }
[Theory]
[InlineData("")]
[InlineData("GetBlogById")]
public void AttributeRoute_ThrowsRouteCreationException_ForConstraintsNotTakingArguments(string routeName)
{
// Arrange
var routeTemplate = "api/Blog/{id:int(10)}";
var actions = new List<ActionDescriptor>()
{
new ActionDescriptor()
{
AttributeRouteInfo = new AttributeRouteInfo()
{
Template = routeTemplate,
Name = routeName
}
},
};
var expectedErrorMessage = "An error occurred while adding a route to the route builder. " +
$"Route name '{routeName}' and template '{routeTemplate}'.";
var builder = CreateBuilder();
var actionDescriptorProvider = CreateActionDescriptorProvider(actions);
var route = CreateRoute(CreateHandler().Object, actionDescriptorProvider.Object);
// Act & Assert
var exception = Assert.Throws<RouteCreationException>(() =>
{
route.AddEntries(builder, actionDescriptorProvider.Object.ActionDescriptors);
});
Assert.Equal(expectedErrorMessage, exception.Message);
Assert.IsType<RouteCreationException>(exception.InnerException);
}
private static TreeRouteBuilder CreateBuilder() private static TreeRouteBuilder CreateBuilder()
{ {
var services = new ServiceCollection() var services = new ServiceCollection()
@ -546,7 +580,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
} }
private static AttributeRoute CreateRoute( private static AttributeRoute CreateRoute(
IRouter handler, IRouter handler,
IActionDescriptorCollectionProvider actionDescriptorProvider) IActionDescriptorCollectionProvider actionDescriptorProvider)
{ {
return CreateRoute((_) => handler, actionDescriptorProvider); return CreateRoute((_) => handler, actionDescriptorProvider);

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var routeContext = new RouteContext(new DefaultHttpContext()); var routeContext = new RouteContext(new DefaultHttpContext());
// Act & Assert // Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => route.RouteAsync(routeContext)); var ex = await Assert.ThrowsAsync<RouteCreationException>(() => route.RouteAsync(routeContext));
Assert.Equal(expectedMessage, ex.Message); Assert.Equal(expectedMessage, ex.Message);
} }
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var route = AttributeRouting.CreateAttributeMegaRoute(services); var route = AttributeRouting.CreateAttributeMegaRoute(services);
// Act & Assert // Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => var ex = await Assert.ThrowsAsync<RouteCreationException>(async () =>
{ {
await route.RouteAsync(new RouteContext(new DefaultHttpContext())); await route.RouteAsync(new RouteContext(new DefaultHttpContext()));
}); });
@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var route = AttributeRouting.CreateAttributeMegaRoute(services); var route = AttributeRouting.CreateAttributeMegaRoute(services);
// Act & Assert // Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => var ex = await Assert.ThrowsAsync<RouteCreationException>(async () =>
{ {
await route.RouteAsync(new RouteContext(new DefaultHttpContext())); await route.RouteAsync(new RouteContext(new DefaultHttpContext()));
}); });
@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
var route = AttributeRouting.CreateAttributeMegaRoute(services); var route = AttributeRouting.CreateAttributeMegaRoute(services);
// Act & Assert // Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => var ex = await Assert.ThrowsAsync<RouteCreationException>(async () =>
{ {
await route.RouteAsync(new RouteContext(new DefaultHttpContext())); await route.RouteAsync(new RouteContext(new DefaultHttpContext()));
}); });