Skip to content

Commit ec2ccaf

Browse files
committed
Adjusted build script to create OpenApiClient artifact, added documentation, minor model adjustments
1 parent 19cc14d commit ec2ccaf

File tree

13 files changed

+105
-56
lines changed

13 files changed

+105
-56
lines changed

Build.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ function CreateNuGetPackage {
8686
if ([string]::IsNullOrWhitespace($versionSuffix)) {
8787
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
8888
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts
89+
dotnet pack .\src\JsonApiDotNetCore.OpenApiClient -c Release -o .\artifacts
8990
}
9091
else {
9192
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$versionSuffix
9293
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts --version-suffix=$versionSuffix
94+
dotnet pack .\src\JsonApiDotNetCore.OpenApiClient -c Release -o .\artifacts --version-suffix=$versionSuffix
9395
}
9496

9597
CheckLastExitCode

JsonApiDotNetCore.sln

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonApiDotNetCore.OpenApi",
4848
EndProject
4949
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}"
5050
EndProject
51-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenApiClient", "src\Examples\OpenApiClient\OpenApiClient.csproj", "{63C2C6C1-0967-4439-BB63-A55DA22869AB}"
52-
EndProject
5351
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonApiDotNetCore.OpenApiClient", "src\JsonApiDotNetCore.OpenApiClient\JsonApiDotNetCore.OpenApiClient.csproj", "{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}"
5452
EndProject
5553
Global
@@ -242,18 +240,6 @@ Global
242240
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU
243241
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU
244242
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU
245-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
246-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
247-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|x64.ActiveCfg = Debug|Any CPU
248-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|x64.Build.0 = Debug|Any CPU
249-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|x86.ActiveCfg = Debug|Any CPU
250-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Debug|x86.Build.0 = Debug|Any CPU
251-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
252-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|Any CPU.Build.0 = Release|Any CPU
253-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|x64.ActiveCfg = Release|Any CPU
254-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|x64.Build.0 = Release|Any CPU
255-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|x86.ActiveCfg = Release|Any CPU
256-
{63C2C6C1-0967-4439-BB63-A55DA22869AB}.Release|x86.Build.0 = Release|Any CPU
257243
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
258244
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
259245
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -286,7 +272,6 @@ Global
286272
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
287273
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
288274
{B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
289-
{63C2C6C1-0967-4439-BB63-A55DA22869AB} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
290275
{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
291276
EndGlobalSection
292277
GlobalSection(ExtensibilityGlobals) = postSolution

docs/usage/openapi.md renamed to docs/usage/openapi/openapi.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public class Startup
3939
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
4040
services.AddJsonApi<AppDbContext>(mvcBuilder: mvcBuilder);
4141

42-
// Adds the Swashbuckle integration.
43-
services.AddOpenApi(mvcBuilder);
42+
// Adds the Swashbuckle integration.
43+
services.AddOpenApi(mvcBuilder);
4444
}
4545

4646
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

docs/usage/openapi/openapiclient.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# OpenAPI Generated Client
2+
3+
Given an OpenAPI specification, you can generate a client library using [NSwag](http://stevetalkscode.co.uk/openapireference-commands). We provide additional methods to enrich the features of this client.
4+
5+
## Installation
6+
7+
You need to install the following NuGet packages:
8+
9+
- `JsonApiDotNetCore.OpenApiClient`
10+
- `NSwag.ApiDescription.Client`
11+
- `Microsoft.Extensions.ApiDescription.Cient`
12+
- `NSwag.ApiDescription.Client`
13+
14+
The following examples demonstrate how to install the `JsonApiDotNetCore.OpenApiClient` package.
15+
16+
### CLI
17+
18+
```
19+
dotnet add package JsonApiDotNetCore.OpenApiClient
20+
```
21+
22+
### Visual Studio
23+
24+
```powershell
25+
Install-Package JsonApiDotNetCore.OpenApiClient
26+
```
27+
28+
### *.csproj
29+
30+
```xml
31+
<ItemGroup>
32+
<!-- Be sure to check NuGet for the latest version # -->
33+
<PackageReference Include="JsonApiDotNetCore.OpenApiClient" Version="4.0.0" />
34+
</ItemGroup>
35+
```
36+
37+
38+
## OpenApiReference
39+
40+
Add a reference to your OpenAPI specification in your project file as demonstrated below.
41+
42+
```xml
43+
<ItemGroup>
44+
<OpenApiReference Include="swagger.json">
45+
<Namespace>YourApplication.GeneratedCode</Namespace>
46+
<ClassName>OpenApiClient</ClassName>
47+
<CodeGenerator>NSwagCSharp</CodeGenerator>
48+
<Options>/UseBaseUrl:false /GenerateClientInterfaces:true</Options>
49+
</OpenApiReference>
50+
</ItemGroup>
51+
```
52+
53+
54+
## Usage
55+
56+
The NSwag tooling generates the OpenAPI client during a prebuild step. Once your application is built,
57+
you can instantiate it using the class name as indicated in the project file.
58+
59+
```c#
60+
using System;
61+
using ApiConsumer.GeneratedCode;
62+
63+
namespace ApiConsumer
64+
{
65+
class Program
66+
{
67+
static void Main(string[] args)
68+
{
69+
70+
using (HttpClient httpClient = new HttpClient())
71+
{
72+
OpenApiClient openApiClient = new OpenApiClient(httpClient);
73+
74+
// IntelliSense is now available on `openApiClient`!
75+
}
76+
}
77+
}
78+
}
79+
```

docs/usage/toc.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
# [Errors](errors.md)
2222
# [Metadata](meta.md)
2323
# [Caching](caching.md)
24-
# [OpenAPI](openapi.md)
24+
25+
# OpenAPI
26+
## [Specification Generator](openapi/openapi.md))
27+
## [Generated Client](openapi/openapiclient.md))
2528

2629
# Extensibility
2730
## [Layer Overview](extensibility/layer-overview.md)

src/JsonApiDotNetCore.OpenApi/SwaggerComponents/JsonApiDataContractResolver.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,6 @@ public DataContract GetDataContractForType(Type type)
5757
return dataContract;
5858
}
5959

60-
private static bool IsIdentifiableBaseType(Type type)
61-
{
62-
if (type.IsGenericType)
63-
{
64-
return type.GetGenericTypeDefinition() == typeof(Identifiable<>);
65-
}
66-
67-
return type == typeof(Identifiable);
68-
}
69-
70-
private static bool IsIdentity(DataProperty property)
71-
{
72-
return property.MemberInfo.Name == nameof(Identifiable.Id);
73-
}
74-
7560
private static DataContract ReplacePropertiesInDataContract(DataContract dataContract, IEnumerable<DataProperty> dataProperties)
7661
{
7762
return DataContract.ForObject(dataContract.UnderlyingType, dataProperties, dataContract.ObjectExtensionDataType,

src/JsonApiDotNetCore.OpenApiClient/JsonApiDotNetCore.OpenApiClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<PropertyGroup>
99
<PackageTags>jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;openapi;swagger;client;nswag</PackageTags>
10-
<Description>TODO</Description>
10+
<Description>Contains utility methods to enrich the usability of an OpenAPI gnerated client.</Description>
1111
<Authors>json-api-dotnet</Authors>
1212
<PackageProjectUrl>https://www.jsonapi.net/</PackageProjectUrl>
1313
<PackageLicenseExpression>MIT</PackageLicenseExpression>

test/OpenApiTests/Airplane.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace OpenApiTests
1010
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
1111
public sealed class Airplane : Identifiable<string>
1212
{
13-
1413
[Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange)]
1514
[Required]
1615
[MaxLength(255)]
@@ -42,7 +41,3 @@ public sealed class Airplane : Identifiable<string>
4241
public ISet<Flight> Flights { get; set; }
4342
}
4443
}
45-
46-
47-
48-

test/OpenApiTests/ClientLibrary/ClientAttributeRegistrationLifeTimeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public async Task Disposed_attribute_registration_for_document_does_not_affect_r
2929
{
3030
Id = airplaneId,
3131
Type = AirplanesResourceType.Airplanes,
32-
Attributes = new AirplaneAttributesInPatchRequest()
32+
Attributes = new AirplaneAttributesInPatchRequest
3333
{
3434
ManufacturedAt = manufacturedAt
3535
}

test/OpenApiTests/ClientLibrary/RequestTests.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ public async Task Partial_patching_resource_produces_expected_request()
181181
};
182182

183183
using (apiClient.RegisterAttributesForRequestDocument<AirplanePatchRequestDocument, AirplaneAttributesInPatchRequest>(requestDocument,
184-
airplane => airplane.ManufacturedAt, airplane => airplane.LastServicedAt, airplane => airplane.IsInMaintenance, airplane => airplane.AirtimeInHours))
184+
airplane => airplane.ManufacturedAt, airplane => airplane.LastServicedAt, airplane => airplane.IsInMaintenance,
185+
airplane => airplane.AirtimeInHours))
185186
{
186187
// Act
187188
_ = await ApiResponse.TranslateAsync(async () => await apiClient.PatchAirplaneAsync(airplaneId, requestDocument));
@@ -293,9 +294,9 @@ public async Task Patching_ToOne_relationship_produces_expected_request()
293294
using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null);
294295
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
295296

296-
var requestDocument = new ToOneAirplaneRequestData()
297+
var requestDocument = new ToOneAirplaneRequestData
297298
{
298-
Data = new AirplaneIdentifier()
299+
Data = new AirplaneIdentifier
299300
{
300301
Id = "bBJHu",
301302
Type = AirplanesResourceType.Airplanes
@@ -348,7 +349,7 @@ public async Task Posting_ToMany_relationship_produces_expected_request()
348349
using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null);
349350
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
350351

351-
var requestDocument = new ToManyFlightAttendantRequestData()
352+
var requestDocument = new ToManyFlightAttendantRequestData
352353
{
353354
Data = new List<FlightAttendantIdentifier>
354355
{
@@ -398,7 +399,7 @@ public async Task Patching_ToMany_relationship_produces_expected_request()
398399
using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null);
399400
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
400401

401-
var requestDocument = new ToManyFlightAttendantRequestData()
402+
var requestDocument = new ToManyFlightAttendantRequestData
402403
{
403404
Data = new List<FlightAttendantIdentifier>
404405
{
@@ -448,7 +449,7 @@ public async Task Deleting_ToMany_relationship_produces_expected_request()
448449
using var wrapper = FakeHttpClientWrapper.Create(HttpStatusCode.NoContent, null);
449450
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
450451

451-
var requestDocument = new ToManyFlightAttendantRequestData()
452+
var requestDocument = new ToManyFlightAttendantRequestData
452453
{
453454
Data = new List<FlightAttendantIdentifier>
454455
{

test/OpenApiTests/ClientLibrary/ResponseTests.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public async Task Posting_resource_translates_response()
283283
Type = FlightsResourceType.Flights,
284284
Relationships = new FlightRelationshipsInPostRequest
285285
{
286-
OperatingAirplane = new ToOneAirplaneRequestData()
286+
OperatingAirplane = new ToOneAirplaneRequestData
287287
{
288288
Data = new AirplaneIdentifier
289289
{
@@ -466,9 +466,9 @@ public async Task Patching_ToOne_relationship_translates_response()
466466
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
467467

468468
// Act
469-
await apiClient.PatchFlightOperatingAirplaneRelationshipAsync(8712, new ToOneAirplaneRequestData()
469+
await apiClient.PatchFlightOperatingAirplaneRelationshipAsync(8712, new ToOneAirplaneRequestData
470470
{
471-
Data = new AirplaneIdentifier()
471+
Data = new AirplaneIdentifier
472472
{
473473
Id = "Adk2a",
474474
Type = AirplanesResourceType.Airplanes
@@ -504,7 +504,8 @@ public async Task Getting_ToMany_relationship_translates_response()
504504
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
505505

506506
// Act
507-
FlightAttendantIdentifierCollectionResponseDocument document = await apiClient.GetFlightFlightAttendantsRelationshipAsync(Convert.ToInt32(flightId));
507+
FlightAttendantIdentifierCollectionResponseDocument
508+
document = await apiClient.GetFlightFlightAttendantsRelationshipAsync(Convert.ToInt32(flightId));
508509

509510
// Assert
510511
document.Data.Should().HaveCount(2);
@@ -522,7 +523,7 @@ public async Task Posting_ToMany_relationship_produces_empty_response()
522523
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
523524

524525
// Act
525-
Func<Task> action = async () => await apiClient.PostFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData()
526+
Func<Task> action = async () => await apiClient.PostFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData
526527
{
527528
Data = new List<FlightAttendantIdentifier>
528529
{
@@ -551,7 +552,7 @@ public async Task Patching_ToMany_relationship_produces_empty_response()
551552
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
552553

553554
// Act
554-
Func<Task> action = async () => await apiClient.PatchFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData()
555+
Func<Task> action = async () => await apiClient.PatchFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData
555556
{
556557
Data = new List<FlightAttendantIdentifier>
557558
{
@@ -580,7 +581,7 @@ public async Task Deleting_ToMany_relationship_produces_empty_response()
580581
IOpenApiClient apiClient = new OpenApiClient(wrapper.HttpClient);
581582

582583
// Act
583-
Func<Task> action = async () => await apiClient.DeleteFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData()
584+
Func<Task> action = async () => await apiClient.DeleteFlightFlightAttendantsRelationshipAsync(8712, new ToManyFlightAttendantRequestData
584585
{
585586
Data = new List<FlightAttendantIdentifier>
586587
{

test/OpenApiTests/Flight.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
// [MaxLength(2000)]
2929
// public string ExternalId { get; set; }
3030

31-
3231
namespace OpenApiTests
3332
{
3433
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
@@ -45,7 +44,7 @@ public sealed class Flight : Identifiable
4544
[Attr]
4645
public DateTime? ArrivesAt { get; set; }
4746

48-
[Attr(PublicName = "operated-by", Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)]
47+
[Attr(PublicName = "operated-by", Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)]
4948
public Airline Airline { get; set; }
5049

5150
[Attr]

test/OpenApiTests/FlightAttendant.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Collections.Generic;
32
using System.ComponentModel.DataAnnotations;
43
using JetBrains.Annotations;

0 commit comments

Comments
 (0)