Merge pull request #6582 from aspnet/rel/2.0.0

Add global filters with the right scope
This commit is contained in:
Pranav K 2017-07-21 14:02:29 -07:00 committed by GitHub
commit 8ab361ae42
7 changed files with 101 additions and 61 deletions

View File

@ -18,12 +18,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
/// Creates a <see cref="CompiledPageActionDescriptor"/> from the specified <paramref name="applicationModel"/>.
/// </summary>
/// <param name="applicationModel">The <see cref="PageApplicationModel"/>.</param>
/// <param name="globalFilters">Global filters to apply to the page.</param>
/// <returns>The <see cref="CompiledPageActionDescriptor"/>.</returns>
public static CompiledPageActionDescriptor Build(PageApplicationModel applicationModel)
public static CompiledPageActionDescriptor Build(
PageApplicationModel applicationModel,
FilterCollection globalFilters)
{
var boundProperties = CreateBoundProperties(applicationModel);
var filters = applicationModel.Filters
.Select(f => new FilterDescriptor(f, FilterScope.Action))
var filters = Enumerable.Concat(
globalFilters.Select(f => new FilterDescriptor(f, FilterScope.Global)),
applicationModel.Filters.Select(f => new FilterDescriptor(f, FilterScope.Action)))
.ToArray();
var handlerMethods = CreateHandlerMethods(applicationModel);

View File

@ -16,16 +16,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public class DefaultPageApplicationModelProvider : IPageApplicationModelProvider
{
private const string ModelPropertyName = "Model";
private readonly FilterCollection _globalFilters;
/// <summary>
/// Initializes a new instance of <see cref="DefaultPageApplicationModelProvider"/>.
/// </summary>
/// <param name="mvcOptions"></param>
public DefaultPageApplicationModelProvider(IOptions<MvcOptions> mvcOptions)
{
_globalFilters = mvcOptions.Value.Filters;
}
/// <inheritdoc />
public int Order => -1000;
@ -146,11 +136,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
internal void PopulateFilters(PageApplicationModel pageModel)
{
for (var i = 0; i < _globalFilters.Count; i++)
{
pageModel.Filters.Add(_globalFilters[i]);
}
for (var i = 0; i < pageModel.HandlerTypeAttributes.Count; i++)
{
if (pageModel.HandlerTypeAttributes[i] is IFilterMetadata filter)

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.Options;
@ -17,11 +18,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private readonly IPageApplicationModelProvider[] _applicationModelProviders;
private readonly IViewCompilerProvider _viewCompilerProvider;
private readonly IPageApplicationModelConvention[] _conventions;
private readonly FilterCollection _globalFilters;
public DefaultPageLoader(
IEnumerable<IPageApplicationModelProvider> applicationModelProviders,
IViewCompilerProvider viewCompilerProvider,
IOptions<RazorPagesOptions> pageOptions)
IOptions<RazorPagesOptions> pageOptions,
IOptions<MvcOptions> mvcOptions)
{
_applicationModelProviders = applicationModelProviders
.OrderBy(p => p.Order)
@ -30,6 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_conventions = pageOptions.Value.Conventions
.OfType<IPageApplicationModelConvention>()
.ToArray();
_globalFilters = mvcOptions.Value.Filters;
}
private IViewCompiler Compiler => _viewCompilerProvider.GetCompiler();
@ -61,7 +65,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_conventions[i].Apply(context.PageApplicationModel);
}
return CompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel);
return CompiledPageActionDescriptorBuilder.Build(context.PageApplicationModel, _globalFilters);
}
}
}

View File

@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private static PageApplicationModelProviderContext GetApplicationProviderContext(TypeInfo typeInfo)
{
var defaultProvider = new DefaultPageApplicationModelProvider(new TestOptionsManager<MvcOptions>());
var defaultProvider = new DefaultPageApplicationModelProvider();
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
defaultProvider.OnProvidersExecuting(context);
return context;

View File

@ -31,9 +31,10 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
};
var handlerTypeInfo = typeof(object).GetTypeInfo();
var pageApplicationModel = new PageApplicationModel(actionDescriptor, handlerTypeInfo, new object[0]);
var globalFilters = new FilterCollection();
// Act
var actual = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel);
var actual = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters);
// Assert
Assert.Same(actionDescriptor.ActionConstraints, actual.ActionConstraints);
@ -78,9 +79,10 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
},
}
};
var globalFilters = new FilterCollection();
// Act
var actual = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel);
var actual = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters);
// Assert
Assert.Same(pageApplicationModel.PageType, actual.PageTypeInfo);
@ -92,6 +94,52 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Assert.Equal(pageApplicationModel.HandlerProperties.Select(p => p.PropertyName), actual.BoundProperties.Select(p => p.Name));
}
[Fact]
public void CreateDescriptor_AddsGlobalFiltersWithTheRightScope()
{
// Arrange
var actionDescriptor = new PageActionDescriptor
{
ActionConstraints = new List<IActionConstraintMetadata>(),
AttributeRouteInfo = new AttributeRouteInfo(),
FilterDescriptors = new List<FilterDescriptor>(),
RelativePath = "/Foo",
RouteValues = new Dictionary<string, string>(),
ViewEnginePath = "/Pages/Foo",
};
var handlerTypeInfo = typeof(TestModel).GetTypeInfo();
var pageApplicationModel = new PageApplicationModel(actionDescriptor, handlerTypeInfo, new object[0])
{
PageType = typeof(TestPage).GetTypeInfo(),
ModelType = typeof(TestModel).GetTypeInfo(),
Filters =
{
Mock.Of<IFilterMetadata>(),
},
};
var globalFilters = new FilterCollection
{
Mock.Of<IFilterMetadata>(),
};
// Act
var compiledPageActionDescriptor = CompiledPageActionDescriptorBuilder.Build(pageApplicationModel, globalFilters);
// Assert
Assert.Collection(
compiledPageActionDescriptor.FilterDescriptors,
filterDescriptor =>
{
Assert.Same(globalFilters[0], filterDescriptor.Filter);
Assert.Equal(FilterScope.Global, filterDescriptor.Scope);
},
filterDescriptor =>
{
Assert.Same(pageApplicationModel.Filters[0], filterDescriptor.Filter);
Assert.Equal(FilterScope.Action, filterDescriptor.Scope);
});
}
private class TestPage
{
public TestModel Model { get; } = new TestModel();

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_ThrowsIfPageDoesNotDeriveFromValidBaseType()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(InvalidPageWithWrongBaseClass).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_ThrowsIfModelPropertyDoesNotExistOnPage()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithoutModelProperty).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_ThrowsIfModelPropertyIsNotPublic()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithNonVisibleModel).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_ThrowsIfModelPropertyIsStatic()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithStaticModel).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_DiscoversPropertiesFromPage_IfModelTypeDoesNotHaveAttribute()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithModelWithoutPageModelAttribute).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -189,7 +189,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_DiscoversPropertiesFromPageModel_IfModelHasAttribute()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithModelWithPageModelAttribute).GetTypeInfo();
var modelType = typeof(ModelWithPageModelAttribute);
var descriptor = new PageActionDescriptor();
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_DiscoversHandlersFromPage()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithModelWithoutHandlers).GetTypeInfo();
var descriptor = new PageActionDescriptor();
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
@ -275,7 +275,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_DiscoversPropertiesFromModel()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithModel).GetTypeInfo();
var modelType = typeof(TestPageModel);
var descriptor = new PageActionDescriptor();
@ -309,7 +309,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_DiscoversHandlersFromModel()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithModel).GetTypeInfo();
var modelType = typeof(TestPageModel);
var descriptor = new PageActionDescriptor();
@ -337,7 +337,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_EmptyPage()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(EmptyPage).GetTypeInfo();
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
@ -358,7 +358,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_EmptyPageModel()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(EmptyPageWithPageModel).GetTypeInfo();
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
@ -426,7 +426,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void CreateDescriptor_FindsHandlerMethod_OnModel()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithHandlerThatGetsIgnored).GetTypeInfo();
var modelType = typeof(ModelWithHandler);
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
@ -473,7 +473,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void OnProvidersExecuting_FindsHandlerMethodOnPage_WhenModelIsNotAnnotatedWithPageModelAttribute()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithHandler).GetTypeInfo();
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
@ -524,7 +524,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_DiscoversHandlersFromBaseType()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(InheritsMethods).GetTypeInfo();
var baseType = typeof(TestSetPageModel);
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -575,7 +575,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_IgnoresNonPublicMethods()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(ProtectedModel).GetTypeInfo();
var baseType = typeof(TestSetPageModel);
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -603,7 +603,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_IgnoreGenericTypeParameters()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(GenericClassModel).GetTypeInfo();
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -626,7 +626,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_IgnoresStaticMethods()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageModelWithStaticHandler).GetTypeInfo();
var expected = typeInfo.GetMethod(nameof(PageModelWithStaticHandler.OnGet), BindingFlags.Public | BindingFlags.Instance);
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -656,7 +656,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_IgnoresAbstractMethods()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageModelWithAbstractMethod).GetTypeInfo();
var expected = typeInfo.GetMethod(nameof(PageModelWithAbstractMethod.OnGet), BindingFlags.Public | BindingFlags.Instance);
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -684,7 +684,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerMethods_IgnoresMethodWithNonHandlerAttribute()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithNonHandlerMethod).GetTypeInfo();
var expected = typeInfo.GetMethod(nameof(PageWithNonHandlerMethod.OnGet), BindingFlags.Public | BindingFlags.Instance);
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -715,7 +715,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void CreateHandlerModel_ParsesMethod()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageModelWithHandlerNames).GetTypeInfo();
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -749,7 +749,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void CreateHandlerMethods_AddsParameterDescriptors()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(PageWithHandlerParameters).GetTypeInfo();
var expected = typeInfo.GetMethod(nameof(PageWithHandlerParameters.OnPost));
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -793,7 +793,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerProperties_UsesPropertyHelpers_ToFindProperties()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(HidesAProperty).GetTypeInfo();
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -826,7 +826,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public void PopulateHandlerProperties_SupportsGet_OnProperty()
{
// Arrange
var provider = new TestPageApplicationModelProvider();
var provider = new DefaultPageApplicationModelProvider();
var typeInfo = typeof(ModelSupportsGetOnProperty).GetTypeInfo();
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
@ -898,14 +898,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Assert.Equal(expectedHandler, handler);
}
private class TestPageApplicationModelProvider : DefaultPageApplicationModelProvider
{
public TestPageApplicationModelProvider(IOptions<MvcOptions> mvcOptions = null)
: base(mvcOptions : new TestOptionsManager<MvcOptions>())
{
}
}
private class PageWithModelWithoutHandlers : Page
{
public ModelWithoutHandler Model { get; }

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
@ -20,7 +21,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var compilerProvider = GetCompilerProvider();
var options = new TestOptionsManager<RazorPagesOptions>();
var razorPagesOptions = new TestOptionsManager<RazorPagesOptions>();
var mvcOptions = new TestOptionsManager<MvcOptions>();
var provider1 = new Mock<IPageApplicationModelProvider>();
var provider2 = new Mock<IPageApplicationModelProvider>();
@ -71,7 +73,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new DefaultPageLoader(
providers,
compilerProvider,
options);
razorPagesOptions,
mvcOptions);
// Act
var result = loader.Load(new PageActionDescriptor());
@ -87,7 +90,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
// Arrange
var descriptor = new PageActionDescriptor();
var compilerProvider = GetCompilerProvider();
var options = new TestOptionsManager<RazorPagesOptions>();
var razorPagesOptions = new TestOptionsManager<RazorPagesOptions>();
var mvcOptions = new TestOptionsManager<MvcOptions>();
var provider1 = new Mock<IPageApplicationModelProvider>();
provider1.SetupGet(p => p.Order).Returns(10);
@ -132,7 +136,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var loader = new DefaultPageLoader(
providers,
compilerProvider,
options);
razorPagesOptions,
mvcOptions);
// Act
var result = loader.Load(new PageActionDescriptor());
@ -159,19 +164,21 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
});
var providers = new[] { provider.Object };
var options = new TestOptionsManager<RazorPagesOptions>();
var razorPagesOptions = new TestOptionsManager<RazorPagesOptions>();
var mvcOptions = new TestOptionsManager<MvcOptions>();
var convention = new Mock<IPageApplicationModelConvention>();
convention.Setup(c => c.Apply(It.IsAny<PageApplicationModel>()))
.Callback((PageApplicationModel m) =>
{
Assert.Same(model, m);
});
options.Value.Conventions.Add(convention.Object);
razorPagesOptions.Value.Conventions.Add(convention.Object);
var loader = new DefaultPageLoader(
providers,
compilerProvider,
options);
razorPagesOptions,
mvcOptions);
// Act
var result = loader.Load(new PageActionDescriptor());