-
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
opt into JsonApi per webapi endpoint #187
opt into JsonApi per webapi endpoint #187
Conversation
@barsh Thanks so much for contributing! A few notes:
config.ConfigureJsonApi(new JsonApiConfiguration(), FormatterPriority.AddFormatterToEnd); Now only requests with the accept request header value of
That effectively enables clients to opt in to JSON API, which may not be what you need. To enable the server to opt in for specific endpoints, I think we need a solution that at least does the same amount of processing that the regular setup does (i.e. supports all features). Ideally we would find a way to make it possible to implement this Perhaps a class void ProcessRequest(HttpRequestMessage request, HttpResponseMessage response) which does the same thing as the delegating handler. Then when a user of Saule implements the What do you think? |
@joukevandermaas I'll have a go at it over the weekend and update this PR |
Saule/Http/JsonApiProcessor.cs
Outdated
|
||
var value = context.Response.Content as ObjectContent; | ||
|
||
var config = new JsonApiConfiguration(); |
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.
@joukevandermaas, I couldn't figure out how to get the configuration, so I created a new one. Is that OK? Is there a way to get the configuration?
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's fine, perhaps we can also create an overload that takes it as a parameter.
Saule/Http/JsonApiProcessor.cs
Outdated
var formatter = new JsonApiMediaTypeFormatter(config).GetPerRequestFormatterInstance( | ||
typeof(string), | ||
context.Request, | ||
new MediaTypeHeaderValue(Constants.MediaType)); |
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.
@joukevandermaas this works but it feels hacky. Is there a better way to get the formatter?
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 could use the constructor overload:
internal JsonApiMediaTypeFormatter(HttpRequestMessage request, JsonApiConfiguration config)
That one is called internally by GetPerRequestFormatterInstance
.
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.
Thanks for making these changes! I think this will enable more fine-grained control over what Saule does, which is great.
There are some tests for the delegating handler. Perhaps they can be copied and changed so we cover both paths?
Other than that I had a few minor questions, but the approach is looking really solid!
Saule/Http/JsonApiProcessor.cs
Outdated
/// process request as JSON API response | ||
/// </summary> | ||
/// <param name="context">context</param> | ||
public static void ProcessRequest(HttpActionExecutedContext 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.
Could this take the HttpRequestMessage
and HttpResponseMessage
(or similar) as parameters? The ActionExecutedContext
is very closely tied to action filters.
Saule/Http/JsonApiProcessor.cs
Outdated
|
||
var value = context.Response.Content as ObjectContent; | ||
|
||
var config = new JsonApiConfiguration(); |
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's fine, perhaps we can also create an overload that takes it as a parameter.
Saule/Http/JsonApiProcessor.cs
Outdated
var formatter = new JsonApiMediaTypeFormatter(config).GetPerRequestFormatterInstance( | ||
typeof(string), | ||
context.Request, | ||
new MediaTypeHeaderValue(Constants.MediaType)); |
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 could use the constructor overload:
internal JsonApiMediaTypeFormatter(HttpRequestMessage request, JsonApiConfiguration config)
That one is called internally by GetPerRequestFormatterInstance
.
Saule/Http/JsonApiProcessor.cs
Outdated
/// <summary> | ||
/// Processes JSON API responses | ||
/// </summary> | ||
public class JsonApiProcessor |
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.
Perhaps this class should be static or sealed.
Saule/Http/JsonApiAttribute.cs
Outdated
/// An optional attribute that can be used to opt an api into returning a JsonApi response. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] | ||
public class JsonApiAttribute : 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.
Should this still be sealed?
Saule/Http/JsonApiProcessor.cs
Outdated
/// <summary> | ||
/// Processes JSON API responses | ||
/// </summary> | ||
public class JsonApiProcessor |
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 you think we can call this from the delegating handler? Now the code is duplicated. I think since this is public, it would be awesome if the delegating handler used the same code-path.
@joukevandermaas I have incorporated all of your feedback. The delegating handler and
Can you give me some direction on where this test should go and point me towards an example that I can use as a reference? |
@barsh awesome! I will review your changes as soon as possible. I think these tests have some setup that should allow you to write the test you propose. They create an http client that talks to some of the endpoints in an example application (see here). You could add a controller or action method there. Alternatively you could create a new file that just tests the new process method you created (whichever you find easier to do). |
@joukevandermaas see added test 0f1b7b2 |
@barsh thanks so much for seeing this through! I'll publish a new pre-release with these changes. |
For existing WebApi projects, that don't use JsonApi/Saule we need a way to preserve backwards compatibility and opt into JsonApi on a case by case basis.
For example:
api/v2/companies
uses the attribute filterJsonApi
which configures it to return a JsonAPI response instead of the default response.With this change, it's not necessary to call
ConfigureJsonApi
during application startup: