Add support for specifying filters on page models.#6417
Conversation
80fdecd to
260e60c
Compare
| } | ||
|
|
||
| // Filters are only allowed to be declared on an explicitly specified model. | ||
| var filters = actionDescriptor.FilterDescriptors; |
There was a problem hiding this comment.
Layering concerns?
| } | ||
|
|
||
| [AttributeUsage(AttributeTargets.Class)] | ||
| public class HandlerChangingPageFilterAttribute : Attribute, IPageFilter |
There was a problem hiding this comment.
Did we intentionally choose not to add a PageFilterAttribute or was that an oversight?
There was a problem hiding this comment.
I chose not to add it. We can if you think it's good
| // 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; |
| var filters = actionDescriptor.FilterDescriptors; | ||
| if (modelType != null && modelType != pageType) | ||
| { | ||
| var modelAttributes = modelType.GetCustomAttributes(inherit: true); |
There was a problem hiding this comment.
Do we want PageModel to implement IPageFilter, IAsyncPageFilter and discover those too?
260e60c to
bf63fe5
Compare
|
🆙 📅 Still in design |
| /// 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.
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.
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.
Call this bound properties (same as controllers)
|
|
||
| public TypeInfo HandlerType { get; } | ||
|
|
||
| public IReadOnlyList<object> HandlerAttributes { get; } |
There was a problem hiding this comment.
This should probably be HandlerTypeAttributes
| /// </summary> | ||
| public string PropertyName { get; set; } | ||
|
|
||
| public bool SupportsGets { get; set; } |
There was a problem hiding this comment.
This is part of binding info now 👍
| TypeInfo pageType, | ||
| TypeInfo modelType, | ||
| TypeInfo handlerType, | ||
| IReadOnlyList<object> handlerAttributes) |
There was a problem hiding this comment.
We should expose the route information here in a read-only format
There was a problem hiding this comment.
What does that look like - something that looks like AttributeRouteInfo?
There was a problem hiding this comment.
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.
These should move to their own providers
rynowak
left a comment
There was a problem hiding this comment.
This looks great! Really on the right track here.
bf63fe5 to
edb1250
Compare
edb1250 to
fa18eba
Compare
|
🆙 📅 |
| /// Gets the sequence of <see cref="PagePropertyModel"/> instances on <see cref="PageHandlerModel"/>. | ||
| /// </summary> | ||
| public IList<SelectorModel> Selectors { get; } | ||
| public IList<PagePropertyModel> HandlerProperties { get; } |
There was a problem hiding this comment.
This should be BoundProperties like it is on controller model
There was a problem hiding this comment.
ControllerModel has ControllerProperties (https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ControllerModel.cs#L96). BoundProperties is on the ControllerAD.
| /// <summary> | ||
| /// Gets the page <see cref="TypeInfo"/>. | ||
| /// </summary> | ||
| public TypeInfo PageType { get; } |
There was a problem hiding this comment.
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.
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.
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.
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.
Either you're with us or you're against us.
There was a problem hiding this comment.
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.
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. |
|
|
||
| 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.
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.
Where would you want them to go? (So I know for the work item)
|
|
||
| var handlerModel = new PageHandlerModel( | ||
| method, | ||
| method.GetCustomAttributes(inherit: false)) |
There was a problem hiding this comment.
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.
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.
I think both of these need to go into MvcOptions. Let's log an issue for this
No description provided.