Skip to content

OpenAPI: Support including related resources #1448

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

Merged
merged 13 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# When running OpenAPI tests, these committed files are downloaded and written to disk (so we'll know when something changes).
# On Windows, these text files are auto-converted to crlf on fetch, while the written downloaded files use lf line endings.
# On Windows, these text files are auto-converted to crlf on git fetch, while the written downloaded files use lf line endings.
# Therefore, running the tests on Windows creates local changes. Staging them auto-converts back to crlf, which undoes the changes.
# To avoid this annoyance, the next line opts out of the auto-conversion and forces to lf.
# To avoid this annoyance, the next lines opt out of the auto-conversion and force to lf.
swagger.g.json text eol=lf
**/GeneratedSwagger/*.json text eol=lf
1 change: 1 addition & 0 deletions JsonApiDotNetCore.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$);</s:String>
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002ETraceAssertPattern/@EntryIndexedValue">50</s:Int64>
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/PropagateAnnotations/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=swagger_002Ejson/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/GeneratedFilesAndFolders/=71287D6F_002D6C3B_002D44B4_002D9FCA_002DE78FE3F02289_002Ff_003ASchemaGenerator_002Ecs/@EntryIndexedValue">71287D6F-6C3B-44B4-9FCA-E78FE3F02289/f:SchemaGenerator.cs</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Eg_002Ejson/@EntryIndexedValue">swagger.g.json</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Ejson/@EntryIndexedValue">swagger.json</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String>
Expand Down
59 changes: 35 additions & 24 deletions docs/usage/openapi-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
You can generate a JSON:API client in various programming languages from the [OpenAPI specification](https://swagger.io/specification/) file that JsonApiDotNetCore APIs provide.

For C# .NET clients generated using [NSwag](https://github.com/RicoSuter/NSwag), we provide an additional package
that introduces support for partial PATCH/POST requests. The concern here is that a property on a generated C# class
being `null` could mean "set the value to `null` in the request" or "this is `null` because I never touched it".
that provides workarounds for NSwag bugs and introduces support for partial PATCH/POST requests.
The concern here is that a property on a generated C# class being `null` could either mean: "set the value to `null`
in the request" or: "this is `null` because I never touched it".

## Getting started

Expand All @@ -26,29 +27,19 @@ The next steps describe how to generate a JSON:API client library and use our pa

3. Although not strictly required, we recommend to run package update now, which fixes some issues.

4. Add code that calls one of your JSON:API endpoints.
> [!WARNING]
> NSwag v14 is currently *incompatible* with JsonApiDotNetCore (tracked [here](https://github.com/RicoSuter/NSwag/issues/4662)). Stick with v13.x for the moment.

```c#
using var httpClient = new HttpClient();
var apiClient = new ExampleApiClient("http://localhost:14140", httpClient);

PersonCollectionResponseDocument getResponse = await apiClient.GetPersonCollectionAsync(new Dictionary<string, string?>
{
["filter"] = "has(assignedTodoItems)",
["sort"] = "-lastName",
["page[size]"] = "5"
});
4. Add our client package to your project:

foreach (PersonDataInResponse person in getResponse.Data)
{
Console.WriteLine($"Found person {person.Id}: {person.Attributes.DisplayName}");
}
```
dotnet add package JsonApiDotNetCore.OpenApi.Client
```

5. Add our client package to your project:
5. Add the next line inside the **OpenApiReference** section in your project file:

```
dotnet add package JsonApiDotNetCore.OpenApi.Client
```xml
<Options>/GenerateExceptionClasses:false /AdditionalNamespaceUsages:JsonApiDotNetCore.OpenApi.Client.Exceptions</Options>
```

6. Add the following glue code to connect our package with your generated code.
Expand All @@ -73,8 +64,28 @@ The next steps describe how to generate a JSON:API client library and use our pa

> [!TIP]
> The project at src/Examples/JsonApiDotNetCoreExampleClient contains an enhanced version that logs the HTTP requests and responses.
> Additionally, the example shows how to write the swagger.json file to disk when building the server, which is imported from the client project. This keeps the server and client automatically in sync, which is handy when both are in the same solution.

7. Add code that calls one of your JSON:API endpoints.

```c#
using var httpClient = new HttpClient();
var apiClient = new ExampleApiClient(httpClient);

var getResponse = await apiClient.GetPersonCollectionAsync(new Dictionary<string, string?>
{
["filter"] = "has(assignedTodoItems)",
["sort"] = "-lastName",
["page[size]"] = "5"
});

foreach (var person in getResponse.Data)
{
Console.WriteLine($"Found person {person.Id}: {person.Attributes.DisplayName}");
}
```

7. Extend your demo code to send a partial PATCH request with the help of our package:
8. Extend your demo code to send a partial PATCH request with the help of our package:

```c#
var patchRequest = new PersonPatchRequestDocument
Expand All @@ -94,7 +105,7 @@ The next steps describe how to generate a JSON:API client library and use our pa
person => person.FirstName))
{
// Workaround for https://github.com/RicoSuter/NSwag/issues/2499.
await TranslateAsync(async () => await apiClient.PatchPersonAsync(patchRequest.Data.Id, null, patchRequest));
await ApiResponse.TranslateAsync(() => apiClient.PatchPersonAsync(patchRequest.Data.Id, null, patchRequest));

// The sent request looks like this:
// {
Expand Down Expand Up @@ -145,13 +156,13 @@ From here, continue from step 3 in the list of steps for Visual Studio.
The `OpenApiReference` element in the project file accepts an `Options` element to pass additional settings to the client generator,
which are listed [here](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs).

For example, the next section puts the generated code in a namespace, removes the `baseUrl` parameter and generates an interface (which is handy for dependency injection):
For example, the next section puts the generated code in a namespace and generates an interface (which is handy for dependency injection):

```xml
<OpenApiReference Include="swagger.json">
<Namespace>ExampleProject.GeneratedCode</Namespace>
<ClassName>SalesApiClient</ClassName>
<CodeGenerator>NSwagCSharp</CodeGenerator>
<Options>/UseBaseUrl:false /GenerateClientInterfaces:true</Options>
<Options>/GenerateClientInterfaces:true</Options>
</OpenApiReference>
```
1 change: 1 addition & 0 deletions package-versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<SwashbuckleFrozenVersion>6.5.0</SwashbuckleFrozenVersion>

<!-- Non-published dependencies (these are safe to update, won't cause a breaking change) -->
<ApiDescriptionServerVersion>8.0.*</ApiDescriptionServerVersion>
<BenchmarkDotNetVersion>0.13.*</BenchmarkDotNetVersion>
<BlushingPenguinVersion>1.0.*</BlushingPenguinVersion>
<BogusVersion>35.2.*</BogusVersion>
Expand Down
Loading