Skip to content

Commit 36a21c6

Browse files
committed
Fixed: relationship endpoints don't support includes
1 parent 64d1503 commit 36a21c6

File tree

13 files changed

+134
-126
lines changed

13 files changed

+134
-126
lines changed

src/Examples/JsonApiDotNetCoreExampleClient/OpenAPIs/swagger.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@
444444
{
445445
"name": "query",
446446
"in": "query",
447-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
447+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
448448
"schema": {
449449
"type": "object",
450450
"additionalProperties": {
@@ -494,7 +494,7 @@
494494
{
495495
"name": "query",
496496
"in": "query",
497-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
497+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
498498
"schema": {
499499
"type": "object",
500500
"additionalProperties": {
@@ -770,7 +770,7 @@
770770
{
771771
"name": "query",
772772
"in": "query",
773-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
773+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
774774
"schema": {
775775
"type": "object",
776776
"additionalProperties": {
@@ -820,7 +820,7 @@
820820
{
821821
"name": "query",
822822
"in": "query",
823-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
823+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
824824
"schema": {
825825
"type": "object",
826826
"additionalProperties": {
@@ -1421,7 +1421,7 @@
14211421
{
14221422
"name": "query",
14231423
"in": "query",
1424-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
1424+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
14251425
"schema": {
14261426
"type": "object",
14271427
"additionalProperties": {
@@ -1471,7 +1471,7 @@
14711471
{
14721472
"name": "query",
14731473
"in": "query",
1474-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
1474+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
14751475
"schema": {
14761476
"type": "object",
14771477
"additionalProperties": {
@@ -2072,7 +2072,7 @@
20722072
{
20732073
"name": "query",
20742074
"in": "query",
2075-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2075+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
20762076
"schema": {
20772077
"type": "object",
20782078
"additionalProperties": {
@@ -2122,7 +2122,7 @@
21222122
{
21232123
"name": "query",
21242124
"in": "query",
2125-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2125+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
21262126
"schema": {
21272127
"type": "object",
21282128
"additionalProperties": {
@@ -2306,7 +2306,7 @@
23062306
{
23072307
"name": "query",
23082308
"in": "query",
2309-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2309+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
23102310
"schema": {
23112311
"type": "object",
23122312
"additionalProperties": {
@@ -2356,7 +2356,7 @@
23562356
{
23572357
"name": "query",
23582358
"in": "query",
2359-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2359+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
23602360
"schema": {
23612361
"type": "object",
23622362
"additionalProperties": {
@@ -2540,7 +2540,7 @@
25402540
{
25412541
"name": "query",
25422542
"in": "query",
2543-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2543+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
25442544
"schema": {
25452545
"type": "object",
25462546
"additionalProperties": {
@@ -2590,7 +2590,7 @@
25902590
{
25912591
"name": "query",
25922592
"in": "query",
2593-
"description": "For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
2593+
"description": "For syntax, see the documentation for the [`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.",
25942594
"schema": {
25952595
"type": "object",
25962596
"additionalProperties": {

src/JsonApiDotNetCore.OpenApi/SwaggerComponents/JsonApiOperationDocumentationFilter.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,17 @@ internal sealed class JsonApiOperationDocumentationFilter : IOperationFilter
3838
private const string TextRequestBodyValidationFailed = "Validation of the request body failed.";
3939
private const string TextRequestBodyClientId = "Client-generated IDs cannot be used at this endpoint.";
4040

41-
private const string TextQueryStringParameters =
41+
private const string ResourceQueryStringParameters =
4242
"For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/" +
4343
"[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/" +
4444
"[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/" +
4545
"[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.";
4646

47+
private const string RelationshipQueryStringParameters = "For syntax, see the documentation for the " +
48+
"[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/" +
49+
"[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/" +
50+
"[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.";
51+
4752
private readonly IJsonApiOptions _options;
4853
private readonly IControllerResourceMapping _controllerResourceMapping;
4954
private readonly ResourceFieldValidationMetadataProvider _resourceFieldValidationMetadataProvider;
@@ -166,7 +171,7 @@ private static void ApplyGetPrimary(OpenApiOperation operation, ResourceType res
166171
$"Successfully returns the found {resourceType}, or an empty array if none were found.");
167172
}
168173

169-
AddQueryStringParameters(operation);
174+
AddQueryStringParameters(operation, false);
170175
SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad);
171176
}
172177
else if (operation.Parameters.Count == 1)
@@ -186,7 +191,7 @@ private static void ApplyGetPrimary(OpenApiOperation operation, ResourceType res
186191
}
187192

188193
SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to retrieve.");
189-
AddQueryStringParameters(operation);
194+
AddQueryStringParameters(operation, false);
190195
SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad);
191196
SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularName} does not exist.");
192197
}
@@ -197,7 +202,7 @@ private void ApplyPostResource(OpenApiOperation operation, ResourceType resource
197202
string singularName = resourceType.PublicName.Singularize();
198203

199204
SetOperationSummary(operation, $"Creates a new {singularName}.");
200-
AddQueryStringParameters(operation);
205+
AddQueryStringParameters(operation, false);
201206
SetRequestBodyDescription(operation.RequestBody, $"The attributes and relationships of the {singularName} to create.");
202207

203208
SetResponseDescription(operation.Responses, HttpStatusCode.Created,
@@ -225,7 +230,7 @@ private void ApplyPatchResource(OpenApiOperation operation, ResourceType resourc
225230

226231
SetOperationSummary(operation, $"Updates an existing {singularName}.");
227232
SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to update.");
228-
AddQueryStringParameters(operation);
233+
AddQueryStringParameters(operation, false);
229234

230235
SetRequestBodyDescription(operation.RequestBody,
231236
$"The attributes and relationships of the {singularName} to update. Omitted fields are left unchanged.");
@@ -278,7 +283,7 @@ relationship is HasOneAttribute
278283
}
279284

280285
SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {rightName} to retrieve.");
281-
AddQueryStringParameters(operation);
286+
AddQueryStringParameters(operation, false);
282287
SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad);
283288
SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} does not exist.");
284289
}
@@ -311,7 +316,7 @@ relationship is HasOneAttribute
311316
}
312317

313318
SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {singularRightName} {ident} to retrieve.");
314-
AddQueryStringParameters(operation);
319+
AddQueryStringParameters(operation, true);
315320
SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad);
316321
SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularLeftName} does not exist.");
317322
}
@@ -427,7 +432,7 @@ private static void SetResponseDescription(OpenApiResponses responses, HttpStatu
427432
response.Description = XmlCommentsTextHelper.Humanize(description);
428433
}
429434

430-
private static void AddQueryStringParameters(OpenApiOperation operation)
435+
private static void AddQueryStringParameters(OpenApiOperation operation, bool isRelationshipEndpoint)
431436
{
432437
// The JSON:API query string parameters (include, filter, sort, page[size], page[number], fields[]) are too dynamic to represent in OpenAPI.
433438
// - The parameter names for fields[] require exploding to all resource types, because outcome of possible resource types depends on
@@ -454,7 +459,7 @@ private static void AddQueryStringParameters(OpenApiOperation operation)
454459
// Prevent SwaggerUI from producing sample, which fails when used because unknown query string parameters are blocked by default.
455460
Example = new OpenApiNull()
456461
},
457-
Description = TextQueryStringParameters
462+
Description = isRelationshipEndpoint ? RelationshipQueryStringParameters : ResourceQueryStringParameters
458463
});
459464
}
460465
}

0 commit comments

Comments
 (0)