Action endpoint metadata contains attributes from action and controller (#8395)

This commit is contained in:
James Newton-King 2018-09-07 10:01:40 +12:00 committed by GitHub
parent 07cc9e66c6
commit 863b1c2c97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 4 deletions

View File

@ -36,6 +36,9 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions
/// </summary> /// </summary>
public IList<IActionConstraintMetadata> ActionConstraints { get; set; } public IList<IActionConstraintMetadata> ActionConstraints { get; set; }
/// <summary>
/// Gets or sets the endpoint metadata for this action.
/// </summary>
public IList<object> EndpointMetadata { get; set; } public IList<object> EndpointMetadata { get; set; }
/// <summary> /// <summary>

View File

@ -138,10 +138,12 @@ namespace Microsoft.AspNetCore.Mvc.Internal
ActionModel action) ActionModel action)
{ {
var defaultControllerConstraints = Enumerable.Empty<IActionConstraintMetadata>(); var defaultControllerConstraints = Enumerable.Empty<IActionConstraintMetadata>();
var defaultControllerEndpointMetadata = Enumerable.Empty<object>();
if (controller.Selectors.Count > 0) if (controller.Selectors.Count > 0)
{ {
defaultControllerConstraints = controller.Selectors[0].ActionConstraints defaultControllerConstraints = controller.Selectors[0].ActionConstraints
.Where(constraint => !(constraint is IRouteTemplateProvider)); .Where(constraint => !(constraint is IRouteTemplateProvider));
defaultControllerEndpointMetadata = controller.Selectors[0].EndpointMetadata;
} }
var actionDescriptors = new List<ControllerActionDescriptor>(); var actionDescriptors = new List<ControllerActionDescriptor>();
@ -164,8 +166,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
AddActionConstraints(actionDescriptor, actionSelector, controllerConstraints); AddActionConstraints(actionDescriptor, actionSelector, controllerConstraints);
// REVIEW: Need to get metadata from controller // Metadata for the action is more significant so order it before the controller metadata
actionDescriptor.EndpointMetadata = actionSelector.EndpointMetadata.ToList(); var actionDescriptorMetadata = actionSelector.EndpointMetadata.ToList();
actionDescriptorMetadata.AddRange(defaultControllerEndpointMetadata);
actionDescriptor.EndpointMetadata = actionDescriptorMetadata;
} }
return actionDescriptors; return actionDescriptors;

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ActionConstraints; using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.ApiExplorer;
@ -252,6 +253,33 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.Equal(nameof(ConventionallyRoutedController.ConventionalAction), actionConstraint.Value); Assert.Equal(nameof(ConventionallyRoutedController.ConventionalAction), actionConstraint.Value);
} }
[Fact]
public void GetDescriptors_EndpointMetadata_ContainsAttributesFromActionAndController()
{
// Arrange & Act
var descriptors = GetDescriptors(
typeof(AuthorizeController).GetTypeInfo());
// Assert
Assert.Equal(2, descriptors.Count());
var anonymousAction = Assert.Single(descriptors, a => a.RouteValues["action"] == "AllowAnonymousAction");
Assert.NotNull(anonymousAction.EndpointMetadata);
Assert.Collection(anonymousAction.EndpointMetadata,
metadata => Assert.IsType<AllowAnonymousAttribute>(metadata),
metadata => Assert.IsType<AuthorizeAttribute>(metadata));
var authorizeAction = Assert.Single(descriptors, a => a.RouteValues["action"] == "AuthorizeAction");
Assert.NotNull(authorizeAction.EndpointMetadata);
Assert.Collection(authorizeAction.EndpointMetadata,
metadata => Assert.Equal("ActionPolicy", Assert.IsType<AuthorizeAttribute>(metadata).Policy),
metadata => Assert.Equal("ControllerPolicy", Assert.IsType<AuthorizeAttribute>(metadata).Policy));
}
[Fact] [Fact]
public void GetDescriptors_ActionWithHttpMethods_AddedToEndpointMetadata() public void GetDescriptors_ActionWithHttpMethods_AddedToEndpointMetadata()
{ {
@ -272,7 +300,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.False(httpMethodMetadata.AcceptCorsPreflight); Assert.False(httpMethodMetadata.AcceptCorsPreflight);
Assert.Equal("GET", Assert.Single(httpMethodMetadata.HttpMethods)); Assert.Equal("GET", Assert.Single(httpMethodMetadata.HttpMethods));
}); },
metadata => Assert.IsType<RouteAttribute>(metadata));
} }
[Fact] [Fact]
@ -1865,6 +1894,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal
public void AttributeRoutedAction() { } public void AttributeRoutedAction() { }
} }
[Authorize("ControllerPolicy")]
private class AuthorizeController
{
[AllowAnonymous]
public void AllowAnonymousAction() { }
[Authorize("ActionPolicy")]
public void AuthorizeAction() { }
}
private class EmptyController private class EmptyController
{ {
} }

View File

@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
} }
[Fact] [Fact]
public void GetDescriptors_CopiesEndPointMetadataFromModel() public void GetDescriptors_CopiesEndpointMetadataFromModel()
{ {
// Arrange // Arrange
var expected = new object(); var expected = new object();