-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add support for specifying filters on page models. #6417
Conversation
80fdecd
to
260e60c
Compare
@@ -59,14 +69,45 @@ public CompiledPageActionDescriptor Load(PageActionDescriptor actionDescriptor) | |||
handlerMethods = CreateHandlerMethods(pageType); | |||
} | |||
|
|||
// Filters are only allowed to be declared on an explicitly specified model. | |||
var filters = actionDescriptor.FilterDescriptors; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Layering concerns?
} | ||
|
||
[AttributeUsage(AttributeTargets.Class)] | ||
public class HandlerChangingPageFilterAttribute : Attribute, IPageFilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we intentionally choose not to add a PageFilterAttribute
or was that an oversight?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose not to add it. We can if you think it's good
@@ -1,6 +1,7 @@ | |||
// 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 Microsoft.AspNetCore.Authorization; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will undo
var filters = actionDescriptor.FilterDescriptors; | ||
if (modelType != null && modelType != pageType) | ||
{ | ||
var modelAttributes = modelType.GetCustomAttributes(inherit: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want PageModel to implement IPageFilter, IAsyncPageFilter
and discover those too?
260e60c
to
bf63fe5
Compare
🆙 📅 Still in design |
/// </summary> | ||
/// <param name="context">The <see cref="PageApplicationModelProviderContext"/>.</param> | ||
void OnProvidersExecuting(PageApplicationModelProviderContext context); | ||
|
||
/// <summary> | ||
/// Executed for the second pass of building <see cref="PageApplicationModel"/> instances. See <see cref="Order"/>. | ||
/// Executed for the second pass of <see cref="ApplicationModel"/> building. See <see cref="Order"/>. | ||
/// </summary> | ||
/// <param name="context">The <see cref="PageApplicationModelProviderContext"/>.</param> | ||
void OnProvidersExecuted(PageApplicationModelProviderContext context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the changes here really clear anything up.
/// </summary> | ||
/// <param name="model">The <see cref="PageRouteModel"/>.</param> | ||
void Apply(PageRouteModel model); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this name, but I don't have a better one in mind.
public IList<SelectorModel> Selectors { get; } | ||
public IList<PageHandlerModel> Handlers { get; } | ||
|
||
public IList<PagePropertyModel> HandlerProperties { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call this bound properties (same as controllers)
|
||
public TypeInfo HandlerType { get; } | ||
|
||
public IReadOnlyList<object> HandlerAttributes { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be HandlerTypeAttributes
/// </summary> | ||
public string PropertyName { get; set; } | ||
|
||
public bool SupportsGets { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is part of binding info now 👍
TypeInfo pageType, | ||
TypeInfo modelType, | ||
TypeInfo handlerType, | ||
IReadOnlyList<object> handlerAttributes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should expose the route information here in a read-only format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does that look like - something that looks like AttributeRouteInfo
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah or maybe just the route template as a string. It's mostly for informational purposes.
pageModel.Filters.Add(new PageSaveTempDataPropertyFilterFactory()); | ||
|
||
// Always require an antiforgery token on post | ||
pageModel.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should move to their own providers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Really on the right track here.
bf63fe5
to
edb1250
Compare
edb1250
to
fa18eba
Compare
🆙 📅 |
/// </summary> | ||
public IList<SelectorModel> Selectors { get; } | ||
public IList<PagePropertyModel> HandlerProperties { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be BoundProperties
like it is on controller model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ControllerModel has ControllerProperties
(https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ControllerModel.cs#L96). BoundProperties
is on the ControllerAD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok 👍
/// <summary> | ||
/// Gets the page <see cref="TypeInfo"/>. | ||
/// </summary> | ||
public TypeInfo PageType { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this here? Isn't this redundant with the AD?
The type isn't super useful on it's own because it's always generated, I'd say just the AD should be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PageActionDescriptor
doesn't have a type info (just the paths). We need to pass this to the provider in some format, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ok, I guess we do need it. 👍
IReadOnlyList<object> attributes) | ||
{ | ||
MethodInfo = handlerMethod ?? throw new ArgumentNullException(nameof(handlerMethod)); | ||
Attributes = attributes ?? throw new ArgumentNullException(nameof(attributes)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry, one of these days all our null checks are going to look like this 😈
if (other == null) | ||
{ | ||
throw new ArgumentNullException(nameof(other)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either you're with us or you're against us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, that's the annoying bit - it only works for assignments, not regular null checks. Super inconsistent. Sort of one of the reasons I wasn't a big fan of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. This is the using static
of this round of features
public string Name { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the seqeunce of <see cref="PageParameterModel"/> instances. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sequence
@@ -157,7 +157,7 @@ public static RazorPagesOptions AuthorizeFolder(this RazorPagesOptions options, | |||
} | |||
|
|||
var authorizeFilter = new AuthorizeFilter(policy); | |||
options.Conventions.Add(new FolderConvention(folderPath, model => model.Filters.Add(authorizeFilter))); | |||
options.ApplicationModelConventions.Add(new FolderApplicationModelConvention(folderPath, model => model.Filters.Add(authorizeFilter))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you log a follow up to deal with the fact that we have a collection of conventions on MvcOptions and RazorPagesOptions. I don't like this but I don't want to block you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where would you want them to go? (So I know for the work item)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know the answer yet
|
||
var handlerModel = new PageHandlerModel( | ||
method, | ||
method.GetCustomAttributes(inherit: false)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We always do inherit: true
for these things
pageApplicationModel.Filters.Add(new PageSaveTempDataPropertyFilterFactory()); | ||
|
||
// Always require an antiforgery token on post | ||
pageApplicationModel.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be separate providers for each of these
/// <summary> | ||
/// Gets a list of <see cref="IPageRouteModelConvention"/> instances that will be applied to | ||
/// the <see cref="PageModel"/> when discovering Razor Pages. | ||
/// </summary> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both of these need to go into MvcOptions
. Let's log an issue for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is beautiful 👍 💯 🍺 🐶 😻
No description provided.