diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs index b615df9df1a96778cec7a0225c54d2c40526d8d8..1500126c495a00b5cb50385f9dae4ca77e666600 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs @@ -398,7 +398,7 @@ namespace Microsoft.AspNetCore.Components public System.Threading.Tasks.Task InvokeAsync(System.Func<System.Threading.Tasks.Task> workItem) { throw null; } public void Render(Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } } - [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=true, Inherited=false)] public partial class RouteAttribute : System.Attribute { public RouteAttribute(string template) { } diff --git a/src/Components/Components/src/RouteAttribute.cs b/src/Components/Components/src/RouteAttribute.cs index f46d04910fa7e6ebe1709cd76d7701400ce763c2..a503dab195548a6f9da88dbef2772ee9c576f7e5 100644 --- a/src/Components/Components/src/RouteAttribute.cs +++ b/src/Components/Components/src/RouteAttribute.cs @@ -1,4 +1,4 @@ -// 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. using System; @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Components /// <summary> /// Indicates that the associated component should match the specified route template pattern. /// </summary> - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public class RouteAttribute : Attribute { /// <summary> diff --git a/src/Components/Components/src/Routing/RouteTable.cs b/src/Components/Components/src/Routing/RouteTable.cs index 0a30f7cbaebafe1039d2e49aac8e59c5e367c86f..4449c00f3cc44bbc8a727e0463907bae41774980 100644 --- a/src/Components/Components/src/Routing/RouteTable.cs +++ b/src/Components/Components/src/Routing/RouteTable.cs @@ -1,4 +1,4 @@ -// 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. using System; @@ -23,7 +23,12 @@ namespace Microsoft.AspNetCore.Components.Routing var routes = new List<RouteEntry>(); foreach (var type in types) { - var routeAttributes = type.GetCustomAttributes<RouteAttribute>(); // Inherit: true? + // We're deliberately using inherit = false here. + // + // RouteAttribute is defined as non-inherited, because inheriting a route attribute always causes an + // ambiguity. You end up with two components (base class and derived class) with the same route. + var routeAttributes = type.GetCustomAttributes<RouteAttribute>(inherit: false); + foreach (var routeAttribute in routeAttributes) { var template = TemplateParser.ParseTemplate(routeAttribute.Template); diff --git a/src/Components/Components/test/Routing/RouteTableTests.cs b/src/Components/Components/test/Routing/RouteTableTests.cs index a4144dcfaf5e5b6ee43991c1ea81f684ec414414..830024940ec908afbb03c95aed5fa2539dbcb19a 100644 --- a/src/Components/Components/test/Routing/RouteTableTests.cs +++ b/src/Components/Components/test/Routing/RouteTableTests.cs @@ -11,6 +11,39 @@ namespace Microsoft.AspNetCore.Components.Test.Routing { public class RouteTableTests { + [Fact] + public void CanDiscoverRoute() + { + // Arrange & Act + var routes = RouteTable.Create(new[] { typeof(MyComponent), }); + + // Assert + Assert.Equal("Test1", Assert.Single(routes.Routes).Template.TemplateText); + } + + [Route("Test1")] + private class MyComponent : ComponentBase + { + } + + [Fact] + public void CanDiscoverRoutes_WithInheritance() + { + // Arrange & Act + var routes = RouteTable.Create(new[] { typeof(MyComponent), typeof(MyInheritedComponent), }); + + // Assert + Assert.Collection( + routes.Routes.OrderBy(r => r.Template.TemplateText), + r => Assert.Equal("Test1", r.Template.TemplateText), + r => Assert.Equal("Test2", r.Template.TemplateText)); + } + + [Route("Test2")] + private class MyInheritedComponent : MyComponent + { + } + [Fact] public void CanMatchRootTemplate() {