-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide ability to handle JsonApi parameters in WebApi action itself manually #181
Provide ability to handle JsonApi parameters in WebApi action itself manually #181
Conversation
…onApi parameters so we can make custom handling for them in the action.
Sorry for the delayed response. Due to the holidays I didn't have time to review this. I will take a look as soon as possible. Thanks for contributing! |
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 really great. 👍
Since we are now making them public API, perhaps we should rename the contexts to something nicer, e.g. FilterContext
, SortContext
, IncludeContext
. Same goes for IncludeProperty
, SortDirection
etc.
Other than that I had a few questions/suggestions but nothing major. Awesome work!
/// Indicates that filter, paging, include and sorting should be parsed. But they won't be automatically applied to WebApi action | ||
/// and action should handle them manually | ||
/// </summary> | ||
public class AllowsManuallyHandledQueryAttribute : ActionFilterAttribute |
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 wonder if this attribute is needed at all? Perhaps it's enough to detect a QueryContext
parameter? I'm not sure if that's possible and if that would still cover the same use cases.
In any case maybe HandlesQuery
or ManuallyHanldesQuery
might be a nicer name?
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 renamed it to HandlesQuery. We can detect this parameter, but we still would need to initialize Sort\Filter\Include like we do in AllowsQueryAttribute
. One way would be to move that detection to AllowsQueryAttribute
, and then it will process them automatically or won't do anything depending on QueryContext
parameter in action. But AllowsQueryAttribute
might be a bit confusing as for me.
There is another point, that HandlesQuery
attribute gives a bit more flexiblity, so developer can use QueryContext
in action, and Saule still can do automatic IQueryable processing if needed. So it's up to developer, but yeah, additional attribute confusing it a bit. One point for future that might makes sense is to combine AllowsQueryAttribute
and HandlesQueryAttribute
and also add such enum to attribute constructor:
public enum AutomaticProcessing
{
None = 0,
Sort = 1,
Pagination = 2,
Include = 4,
Filter = 8,
All = Sort | Pagination | Include | Filter
}
So we can specify it in such way:
public IHttpActionResult Get()
{
}
and it will initialize all query context properties from request, but will apply only filtering on action result. And all other actions won't be applied. So it would have more precise way to configure what needs to be processed and what not. And then in my case i can specify AllowsQuery(AutomaticProcissing.None)
that will be equivalent to current HandlesQueryAttribute
and then handle QueryContext
in action itself.
If you like this idea, i can update the code.
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 do like it, but I also feel that the current approach is probably simpler. If we ever do a Saule 2.0 I'll consider cleaning up the attribute situation.
[HttpGet] | ||
[AllowsManuallyHandledQuery] | ||
[Paginated] | ||
[DisableDefaultIncluded] |
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.
Does DisableDefaultIncluded
make sense in combination with ManuallyHandlesQuery
? At first glance it does not and maybe it should error (?). If that's hard then IMO ManuallyHandlesQuery
should take precedence and all other query-related attributes should be ignored.
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.
That makes sense. I've added validation to HandlesQueryAttribute
, so it will return an error when any\both DisableDefaultIncluded
\ AllowsQuery
are specified.
renamed Including\Filtering\Sorting properties in the same way renamed AllowsManuallyHandledQueryAttribute to HandlesQueryAttribute added validations to HandlesQueryAttribute
Sorry, for long answer. pushed change with such renames\changes:
Also added answers to your comments |
Great! I will publish a new pre-release with these changes in it. Thanks for the hard work! 🎉 |
Thanks! |
Hi Jouke,
Here is pull request for issue #120 . In our case we don't use EntityFramework, but we want to consume already parsed parameters (include\filters\page\sort), so then we can handle them manually in our WebApi controllers\actions. Current issue is that if i specify
AllowsQueryAttribute
, then Saule will parse request and will try to apply it automatically that isn't what we need. I tried to follow your comments in that ticket by makingQueryContext
as publicly accessible, but with internal setters, so for external callers it will be immutableThis pull request tries to handle such use cases:
QueryContext
to WebApi action, so action can handle it manually. There is a code inAllowsManuallyHandledQueryAttribute
that passes currentQueryContext
to action if action has it as parameter. For example in case of Include, we can check what properties were specified inQueryContext
and only then we would load them from our persistent storage. Otherwise we won't load them. Currently Saule does't allow to us to do it and we need to load the whole entity withDisableDefaultIncluded
attribute, and then Saule will include specified properties. But not all consumer needs all properties.&filter[include-ancient-records]=true
and right now Saule will fail here as it requires thatIncludeAncientRecords
should be present in entity itselfJsonApiQueryValueProvider
that gets parameters from query, and then converts them to PascalCase, so WebApi can bind them. Use case here is that we can have ownPersonFilter
like in added tests, where i can specify custom properties. I'm a bit afraid that it will affect something else, but it should be used after defaultQueryStringValueProvider
so it will have lower priority in model bindingI added 19 unit tests that should validate these cases. And also i verified that existing unit tests are still valid and passes.
I also have some doubts about naming and not sure that
ManuallyHandledQuery
is good description for that, so i'm totally open for any other suggestions.I haven't updated any docs, as i'm sure you will have some comments about code and it might need more changes. but if you want, i can add some documenation to docs/content folder about this feature
Thanks!