Skip to content

Commit 3220fc8

Browse files
authored
Merge 8d50846 into e9c44c9
2 parents e9c44c9 + 8d50846 commit 3220fc8

File tree

147 files changed

+22031
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+22031
-3
lines changed

Build.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ function CreateNuGetPackage {
9898
CheckLastExitCode
9999
}
100100

101+
# In a PR the base branch needs to be fetched in order for regitlint to work.
102+
function FetchBaseBranchIfNotMaster() {
103+
if ($env:APPVEYOR_PULL_REQUEST_NUMBER -And $env:APPVEYOR_REPO_BRANCH -ne "master") {
104+
git fetch -q origin ${env:APPVEYOR_REPO_BRANCH}:${env:APPVEYOR_REPO_BRANCH}
105+
}
106+
}
107+
108+
FetchBaseBranchIfNotMaster
109+
101110
dotnet tool restore
102111
CheckLastExitCode
103112

Directory.Build.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
<EFCorePostgresVersion>7.0.*</EFCorePostgresVersion>
77
<MicrosoftCodeAnalysisVersion>4.4.*</MicrosoftCodeAnalysisVersion>
88
<HumanizerVersion>2.14.1</HumanizerVersion>
9+
<SwashbuckleVersion>6.4.*</SwashbuckleVersion>
10+
<NSwagApiClientVersion>13.16.*</NSwagApiClientVersion>
11+
<MicrosoftApiClientVersion>6.0.*</MicrosoftApiClientVersion>
12+
<NewtonsoftJsonVersion>13.0.*</NewtonsoftJsonVersion>
913
<JsonApiDotNetCoreVersionPrefix>5.1.3</JsonApiDotNetCoreVersionPrefix>
1014
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodingGuidelines.ruleset</CodeAnalysisRuleSet>
1115
<WarningLevel>9999</WarningLevel>

JsonApiDotNetCore.sln

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabasePerTenantExample",
5555
EndProject
5656
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnnotationTests", "test\AnnotationTests\AnnotationTests.csproj", "{24B0C12F-38CD-4245-8785-87BEFAD55B00}"
5757
EndProject
58+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi", "src\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}"
59+
EndProject
60+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}"
61+
EndProject
62+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client", "src\JsonApiDotNetCore.OpenApi.Client\JsonApiDotNetCore.OpenApi.Client.csproj", "{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}"
63+
EndProject
64+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreExampleClient", "src\Examples\JsonApiDotNetCoreExampleClient\JsonApiDotNetCoreExampleClient.csproj", "{7FC5DFA3-6F66-4FD8-820D-81E93856F252}"
65+
EndProject
66+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiClientTests", "test\OpenApiClientTests\OpenApiClientTests.csproj", "{77F98215-3085-422E-B99D-4C404C2114CF}"
67+
EndProject
5868
Global
5969
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6070
Debug|Any CPU = Debug|Any CPU
@@ -281,6 +291,66 @@ Global
281291
{24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x64.Build.0 = Release|Any CPU
282292
{24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.ActiveCfg = Release|Any CPU
283293
{24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.Build.0 = Release|Any CPU
294+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
295+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU
296+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU
297+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU
298+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU
299+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU
300+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU
301+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU
302+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU
303+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU
304+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU
305+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU
306+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
307+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU
308+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU
309+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU
310+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU
311+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU
312+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU
313+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU
314+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU
315+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU
316+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU
317+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU
318+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
319+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
320+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.ActiveCfg = Debug|Any CPU
321+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.Build.0 = Debug|Any CPU
322+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.ActiveCfg = Debug|Any CPU
323+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.Build.0 = Debug|Any CPU
324+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
325+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.Build.0 = Release|Any CPU
326+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.ActiveCfg = Release|Any CPU
327+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.Build.0 = Release|Any CPU
328+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.ActiveCfg = Release|Any CPU
329+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.Build.0 = Release|Any CPU
330+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
331+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.Build.0 = Debug|Any CPU
332+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.ActiveCfg = Debug|Any CPU
333+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.Build.0 = Debug|Any CPU
334+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.ActiveCfg = Debug|Any CPU
335+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.Build.0 = Debug|Any CPU
336+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.ActiveCfg = Release|Any CPU
337+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.Build.0 = Release|Any CPU
338+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.ActiveCfg = Release|Any CPU
339+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.Build.0 = Release|Any CPU
340+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.ActiveCfg = Release|Any CPU
341+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.Build.0 = Release|Any CPU
342+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
343+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
344+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.ActiveCfg = Debug|Any CPU
345+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.Build.0 = Debug|Any CPU
346+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.ActiveCfg = Debug|Any CPU
347+
{77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.Build.0 = Debug|Any CPU
348+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
349+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.Build.0 = Release|Any CPU
350+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.ActiveCfg = Release|Any CPU
351+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.Build.0 = Release|Any CPU
352+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.ActiveCfg = Release|Any CPU
353+
{77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.Build.0 = Release|Any CPU
284354
EndGlobalSection
285355
GlobalSection(SolutionProperties) = preSolution
286356
HideSolutionNode = FALSE
@@ -304,6 +374,11 @@ Global
304374
{83FF097C-C8C6-477B-9FAB-DF99B84978B5} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
305375
{60334658-BE51-43B3-9C4D-F2BBF56C89CE} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
306376
{24B0C12F-38CD-4245-8785-87BEFAD55B00} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
377+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
378+
{B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
379+
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
380+
{7FC5DFA3-6F66-4FD8-820D-81E93856F252} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
381+
{77F98215-3085-422E-B99D-4C404C2114CF} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
307382
EndGlobalSection
308383
GlobalSection(ExtensibilityGlobals) = postSolution
309384
SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4}

JsonApiDotNetCore.sln.DotSettings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$);</s:String>
1414
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002EThrowExpressionNullCheckPattern/@EntryIndexedValue">3000</s:Int64>
1515
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002ETraceAssertPattern/@EntryIndexedValue">50</s:Int64>
1616
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/PropagateAnnotations/@EntryValue">False</s:Boolean>
17+
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=swagger_002Ejson/@EntryIndexedValue">True</s:Boolean>
18+
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Eg_002Ejson/@EntryIndexedValue">swagger.g.json</s:String>
19+
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Ejson/@EntryIndexedValue">swagger.json</s:String>
1720
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String>
1821
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/IdentifierHighlightingEnabled/@EntryValue">True</s:Boolean>
1922
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/IncludeWarningsInSwea/@EntryValue">True</s:Boolean>

appveyor.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ environment:
1515
branches:
1616
only:
1717
- master
18+
- openapi
1819
- develop
1920
- unstable
2021
- /release\/.+/
@@ -70,7 +71,7 @@ for:
7071
CD _site
7172
git add -A 2>&1
7273
git commit -m "Automated commit from cibuild" -q
73-
if (-Not $env:APPVEYOR_PULL_REQUEST_TITLE) {
74+
if (-Not $env:APPVEYOR_PULL_REQUEST_TITLE -And $env:APPVEYOR_REPO_BRANCH -eq 'master') {
7475
git push origin gh-pages -q
7576
echo "Documentation updated successfully."
7677
}

docs/usage/openapi-client.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# OpenAPI Client
2+
3+
You can generate a JSON:API client in various programming languages from the [OpenAPI specification](https://swagger.io/specification/) file that JsonApiDotNetCore APIs provide.
4+
5+
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 issue 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".
6+
7+
## Getting started
8+
9+
### Visual Studio
10+
11+
The easiest way to get started is by using the built-in capabilities of Visual Studio. The next steps describe how to generate a JSON:API client library and use our package.
12+
13+
1. In **Solution Explorer**, right-click your client project, select **Add** > **Service Reference** and choose **OpenAPI**.
14+
15+
2. On the next page, specify the OpenAPI URL to your JSON:API server, for example: `http://localhost:14140/swagger/v1/swagger.json`.
16+
Optionally provide a class name and namespace and click **Finish**.
17+
Visual Studio now downloads your swagger.json and updates your project file. This results in a pre-build step that generates the client code.
18+
19+
Tip: To later re-download swagger.json and regenerate the client code, right-click **Dependencies** > **Manage Connected Services** and click the **Refresh** icon.
20+
3. Although not strictly required, we recommend to run package update now, which fixes some issues and removes the `Stream` parameter from generated calls.
21+
22+
4. Add some demo code that calls one of your JSON:API endpoints. For example:
23+
24+
```c#
25+
using var httpClient = new HttpClient();
26+
var apiClient = new ExampleApiClient("http://localhost:14140", httpClient);
27+
28+
PersonCollectionResponseDocument getResponse =
29+
await apiClient.GetPersonCollectionAsync();
30+
31+
foreach (PersonDataInResponse person in getResponse.Data)
32+
{
33+
Console.WriteLine($"Found user {person.Id} named " +
34+
$"'{person.Attributes.FirstName} {person.Attributes.LastName}'.");
35+
}
36+
```
37+
38+
5. Add our client package to your project:
39+
40+
```
41+
dotnet add package JsonApiDotNetCore.OpenApi.Client
42+
```
43+
44+
6. Add the following glue code to connect our package with your generated code. The code below assumes you specified `ExampleApiClient` as class name in step 2.
45+
46+
```c#
47+
using JsonApiDotNetCore.OpenApi.Client;
48+
using Newtonsoft.Json;
49+
50+
partial class ExampleApiClient : JsonApiClient
51+
{
52+
partial void UpdateJsonSerializerSettings(JsonSerializerSettings settings)
53+
{
54+
SetSerializerSettingsForJsonApi(settings);
55+
}
56+
}
57+
```
58+
59+
7. Extend your demo code to send a partial PATCH request with the help of our package:
60+
61+
```c#
62+
var patchRequest = new PersonPatchRequestDocument
63+
{
64+
Data = new PersonDataInPatchRequest
65+
{
66+
Id = "1",
67+
Attributes = new PersonAttributesInPatchRequest
68+
{
69+
FirstName = "Jack"
70+
}
71+
}
72+
};
73+
74+
// This line results in sending "lastName: null" instead of omitting it.
75+
using (apiClient.RegisterAttributesForRequestDocument<PersonPatchRequestDocument,
76+
PersonAttributesInPatchRequest>(patchRequest, person => person.LastName))
77+
{
78+
PersonPrimaryResponseDocument patchResponse =
79+
await apiClient.PatchPersonAsync("1", patchRequest);
80+
81+
// The sent request looks like this:
82+
// {
83+
// "data": {
84+
// "type": "people",
85+
// "id": "1",
86+
// "attributes": {
87+
// "firstName": "Jack",
88+
// "lastName": null
89+
// }
90+
// }
91+
// }
92+
}
93+
```
94+
95+
### Other IDEs
96+
97+
When using the command-line, you can try the [Microsoft.dotnet-openapi Global Tool](https://docs.microsoft.com/en-us/aspnet/core/web-api/microsoft.dotnet-openapi?view=aspnetcore-5.0).
98+
99+
Alternatively, the next section shows what to add to your client project file directly:
100+
101+
```xml
102+
<ItemGroup>
103+
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="3.0.0">
104+
<PrivateAssets>all</PrivateAssets>
105+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
106+
</PackageReference>
107+
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
108+
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.0.5">
109+
<PrivateAssets>all</PrivateAssets>
110+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
111+
</PackageReference>
112+
</ItemGroup>
113+
114+
<ItemGroup>
115+
<OpenApiReference Include="OpenAPIs\swagger.json" CodeGenerator="NSwagCSharp" ClassName="ExampleApiClient">
116+
<SourceUri>http://localhost:14140/swagger/v1/swagger.json</SourceUri>
117+
</OpenApiReference>
118+
</ItemGroup>
119+
```
120+
121+
From here, continue from step 3 in the list of steps for Visual Studio.
122+
123+
## Configuration
124+
125+
### NSwag
126+
127+
The `OpenApiReference` element in the project file accepts an `Options` element to pass additional settings to the client generator,
128+
which are listed [here](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs).
129+
130+
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):
131+
132+
```xml
133+
<OpenApiReference Include="swagger.json">
134+
<Namespace>ExampleProject.GeneratedCode</Namespace>
135+
<ClassName>SalesApiClient</ClassName>
136+
<CodeGenerator>NSwagCSharp</CodeGenerator>
137+
<Options>/UseBaseUrl:false /GenerateClientInterfaces:true</Options>
138+
</OpenApiReference>
139+
```

docs/usage/openapi.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# OpenAPI
2+
3+
JsonApiDotNetCore provides an extension package that enables you to produce an [OpenAPI specification](https://swagger.io/specification/) for your JSON:API endpoints. This can be used to generate a [documentation website](https://swagger.io/tools/swagger-ui/) or to generate [client libraries](https://openapi-generator.tech/docs/generators/) in various languages. The package provides an integration with [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore).
4+
5+
6+
## Getting started
7+
8+
1. Install the `JsonApiDotNetCore.OpenApi` NuGet package:
9+
10+
```
11+
dotnet add package JsonApiDotNetCore.OpenApi
12+
```
13+
14+
2. Add the integration in your `Program.cs` file.
15+
16+
```c#
17+
IMvcCoreBuilder mvcCoreBuilder = builder.Services.AddMvcCore();
18+
19+
builder.Services.AddJsonApi<AppDbContext>(mvcBuilder: mvcCoreBuilder);
20+
21+
// Configures Swashbuckle for JSON:API.
22+
builder.Services.AddOpenApi(mvcCoreBuilder);
23+
24+
var app = builder.Build();
25+
26+
app.UseRouting();
27+
app.UseJsonApi();
28+
29+
// Adds the Swashbuckle middleware.
30+
app.UseSwagger();
31+
```
32+
33+
By default, the OpenAPI specification will be available at `http://localhost:<port>/swagger/v1/swagger.json`.
34+
35+
## Documentation
36+
37+
Swashbuckle also ships with [SwaggerUI](https://swagger.io/tools/swagger-ui/), tooling for a generated documentation page. This can be enabled by installing the `Swashbuckle.AspNetCore.SwaggerUI` NuGet package and adding the following to your `Program.cs` file:
38+
39+
```c#
40+
app.UseSwaggerUI();
41+
```
42+
43+
By default, SwaggerUI will be available at `http://localhost:<port>/swagger`.

docs/usage/toc.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
# [Common Pitfalls](common-pitfalls.md)
2828

29+
# [OpenAPI](openapi.md)
30+
## [Client](openapi-client.md)
31+
2932
# Extensibility
3033
## [Layer Overview](extensibility/layer-overview.md)
3134
## [Resource Definitions](extensibility/resource-definitions.md)

src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
<ProjectReference Include="..\..\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
88
<ProjectReference Include="..\..\JsonApiDotNetCore.SourceGenerators\JsonApiDotNetCore.SourceGenerators.csproj" OutputItemType="Analyzer"
99
ReferenceOutputAssembly="false" />
10+
<ProjectReference Include="..\..\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
1011
</ItemGroup>
1112

1213
<ItemGroup>
1314
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
1415
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(EFCorePostgresVersion)" />
16+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="$(SwashbuckleVersion)" />
1517
</ItemGroup>
1618
</Project>

src/Examples/JsonApiDotNetCoreExample/Program.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Text.Json.Serialization;
33
using JsonApiDotNetCore.Configuration;
44
using JsonApiDotNetCore.Diagnostics;
5+
using JsonApiDotNetCore.OpenApi;
56
using JsonApiDotNetCoreExample.Data;
67
using Microsoft.AspNetCore.Authentication;
78
using Microsoft.EntityFrameworkCore;
@@ -56,6 +57,8 @@ static void ConfigureServices(WebApplicationBuilder builder)
5657
#endif
5758
});
5859

60+
IMvcCoreBuilder mvcCoreBuilder = builder.Services.AddMvcCore();
61+
5962
using (CodeTimingSessionManager.Current.Measure("AddJsonApi()"))
6063
{
6164
builder.Services.AddJsonApi<AppDbContext>(options =>
@@ -69,7 +72,12 @@ static void ConfigureServices(WebApplicationBuilder builder)
6972
options.IncludeExceptionStackTraceInErrors = true;
7073
options.IncludeRequestBodyInErrors = true;
7174
#endif
72-
}, discovery => discovery.AddCurrentAssembly());
75+
}, discovery => discovery.AddCurrentAssembly(), mvcBuilder: mvcCoreBuilder);
76+
}
77+
78+
using (CodeTimingSessionManager.Current.Measure("AddOpenApi()"))
79+
{
80+
builder.Services.AddOpenApi(mvcCoreBuilder);
7381
}
7482
}
7583

@@ -90,6 +98,9 @@ static void ConfigurePipeline(WebApplication webApplication)
9098
webApplication.UseJsonApi();
9199
}
92100

101+
webApplication.UseSwagger();
102+
webApplication.UseSwaggerUI();
103+
93104
webApplication.MapControllers();
94105
}
95106

0 commit comments

Comments
 (0)