Make RouteAttribute non-inherited (#10236)

* Make RouteAttribute non-inherited

Fixes: #5529

Inheriting and looking for inherited route attributes will cause nothing
but trouble. We had a bug tracking what to do about this and we decided
to make it really clear that routes are not inherited.

Previously the attribute was marked as inherited, but we woulnd't look
for inherited routes.

* add test
This commit is contained in:
Ryan Nowak 2019-05-14 15:37:17 -07:00 committed by GitHub
parent 07a02dcbc7
commit d794c52c75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 5 deletions

View File

@ -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) { }

View File

@ -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>

View File

@ -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);

View File

@ -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()
{