diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs index d6bc8c8f68..2a366fab18 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs @@ -120,7 +120,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal subTemplate, endpointInfo.Defaults, ++conventionalRouteOrder, - endpointInfo); + endpointInfo, + suppressLinkGeneration: false); endpoints.Add(subEndpoint); } @@ -145,7 +146,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal newTemplate, endpointInfo.Defaults, ++conventionalRouteOrder, - endpointInfo); + endpointInfo, + suppressLinkGeneration: false); endpoints.Add(endpoint); } } @@ -158,7 +160,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal action.AttributeRouteInfo.Template, nonInlineDefaults: null, action.AttributeRouteInfo.Order, - action.AttributeRouteInfo); + action.AttributeRouteInfo, + suppressLinkGeneration: action.AttributeRouteInfo.SuppressLinkGeneration); endpoints.Add(endpoint); } } @@ -266,7 +269,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal string template, object nonInlineDefaults, int order, - object source) + object source, + bool suppressLinkGeneration) { RequestDelegate invokerDelegate = (context) => { @@ -289,7 +293,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal var defaults = new RouteValueDictionary(nonInlineDefaults); EnsureRequiredValuesInDefaults(action.RouteValues, defaults); - var metadataCollection = BuildEndpointMetadata(action, routeName, source); + var metadataCollection = BuildEndpointMetadata(action, routeName, source, suppressLinkGeneration); var endpoint = new MatcherEndpoint( next => invokerDelegate, RoutePatternFactory.Parse(template, defaults, constraints: null), @@ -301,7 +305,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal return endpoint; } - private static EndpointMetadataCollection BuildEndpointMetadata(ActionDescriptor action, string routeName, object source) + private static EndpointMetadataCollection BuildEndpointMetadata( + ActionDescriptor action, + string routeName, + object source, + bool suppressLinkGeneration) { var metadata = new List(); // REVIEW: Used for debugging. Consider removing before release @@ -341,6 +349,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal } } + if (suppressLinkGeneration) + { + metadata.Add(new SuppressLinkGenerationMetadata()); + } + var metadataCollection = new EndpointMetadataCollection(metadata); return metadataCollection; } @@ -428,5 +441,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal public string Name { get; } } + + private class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata { } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/GlobalRoutingUrlHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/GlobalRoutingUrlHelperTest.cs index b207c8dda4..4c59c5b104 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/GlobalRoutingUrlHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Routing/GlobalRoutingUrlHelperTest.cs @@ -93,6 +93,24 @@ namespace Microsoft.AspNetCore.Mvc.Routing Assert.Equal("/api/orders/10", url); } + [Fact] + public void RouteUrl_DoesNotGenerateLink_ToEndpointsWithSuppressLinkGeneration() + { + // Arrange + var endpoint = CreateEndpoint( + "Home/Index", + defaults: new { controller = "Home", action = "Index" }, + requiredValues: new { controller = "Home", action = "Index" }, + metadataCollection: new EndpointMetadataCollection(new[] { new SuppressLinkGenerationMetadata() })); + var urlHelper = CreateUrlHelper(new[] { endpoint }); + + // Act + var url = urlHelper.RouteUrl(new { controller = "Home", action = "Index" }); + + // Assert + Assert.Null(url); + } + protected override IUrlHelper CreateUrlHelper(string appRoot, string host, string protocol) { return CreateUrlHelper(Enumerable.Empty(), appRoot, host, protocol); @@ -313,5 +331,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing public string Name { get; } } + + private class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata { } } }