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>
public IList<IActionConstraintMetadata> ActionConstraints { get; set; }
/// <summary>
/// Gets or sets the endpoint metadata for this action.
/// </summary>
public IList<object> EndpointMetadata { get; set; }
/// <summary>

View File

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

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
@ -252,6 +253,33 @@ namespace Microsoft.AspNetCore.Mvc.Internal
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]
public void GetDescriptors_ActionWithHttpMethods_AddedToEndpointMetadata()
{
@ -272,7 +300,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.False(httpMethodMetadata.AcceptCorsPreflight);
Assert.Equal("GET", Assert.Single(httpMethodMetadata.HttpMethods));
});
},
metadata => Assert.IsType<RouteAttribute>(metadata));
}
[Fact]
@ -1865,6 +1894,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal
public void AttributeRoutedAction() { }
}
[Authorize("ControllerPolicy")]
private class AuthorizeController
{
[AllowAnonymous]
public void AllowAnonymousAction() { }
[Authorize("ActionPolicy")]
public void AuthorizeAction() { }
}
private class EmptyController
{
}

View File

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