Skip to content

Commit 60adeac

Browse files
authored
Merge c236cad into a3890fe
2 parents a3890fe + c236cad commit 60adeac

23 files changed

+1375
-3
lines changed

Build.ps1

+11
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,25 @@ function CreateNuGetPackage {
8585

8686
if ([string]::IsNullOrWhitespace($versionSuffix)) {
8787
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
88+
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts
8889
}
8990
else {
9091
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$versionSuffix
92+
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts --version-suffix=$versionSuffix
9193
}
9294

9395
CheckLastExitCode
9496
}
9597

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

Directory.Build.props

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<AspNetCoreVersion>5.0.*</AspNetCoreVersion>
55
<EFCoreVersion>5.0.*</EFCoreVersion>
66
<NpgsqlPostgreSQLVersion>5.0.*</NpgsqlPostgreSQLVersion>
7+
<SwashbuckleVersion>6.2.*</SwashbuckleVersion>
8+
<JsonApiDotNetCoreVersionPrefix>4.2.0</JsonApiDotNetCoreVersionPrefix>
79
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodingGuidelines.ruleset</CodeAnalysisRuleSet>
810
</PropertyGroup>
911

JsonApiDotNetCore.sln

+30
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextTests", "test
4444
EndProject
4545
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBuildingBlocks", "test\TestBuildingBlocks\TestBuildingBlocks.csproj", "{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}"
4646
EndProject
47+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonApiDotNetCore.OpenApi", "src\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}"
48+
EndProject
49+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}"
50+
EndProject
4751
Global
4852
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4953
Debug|Any CPU = Debug|Any CPU
@@ -210,6 +214,30 @@ Global
210214
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.Build.0 = Release|Any CPU
211215
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.ActiveCfg = Release|Any CPU
212216
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.Build.0 = Release|Any CPU
217+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
218+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU
219+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU
220+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU
221+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU
222+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU
223+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU
224+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU
225+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU
226+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU
227+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU
228+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU
229+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
230+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU
231+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU
232+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU
233+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU
234+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU
235+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU
236+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU
237+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU
238+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU
239+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU
240+
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU
213241
EndGlobalSection
214242
GlobalSection(SolutionProperties) = preSolution
215243
HideSolutionNode = FALSE
@@ -228,6 +256,8 @@ Global
228256
{6CAFDDBE-00AB-4784-801B-AB419C3C3A26} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
229257
{EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
230258
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
259+
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
260+
{B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
231261
EndGlobalSection
232262
GlobalSection(ExtensibilityGlobals) = postSolution
233263
SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4}

appveyor.yml

+1
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\/.+/

docs/usage/extensibility/middleware.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class Startup
2727
{
2828
services.AddSingleton<CustomAsyncQueryStringActionFilter>();
2929

30-
IMvcCoreBuilder builder = services.AddMvcCore();
30+
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
3131
services.AddJsonApi<AppDbContext>(mvcBuilder: builder);
3232

3333
// Ensure this call is placed after the AddJsonApi call.

docs/usage/openapi.md

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# OpenAPI
2+
3+
You can describe your API with an OpenAPI specification using the [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) integration for JsonApiDotNetCore.
4+
5+
## Installation
6+
7+
Install the `JsonApiDotNetCore.OpenApi` NuGet package.
8+
9+
### CLI
10+
11+
```
12+
dotnet add package JsonApiDotNetCore.OpenApi
13+
```
14+
15+
### Visual Studio
16+
17+
```powershell
18+
Install-Package JsonApiDotNetCore.OpenApi
19+
```
20+
21+
### *.csproj
22+
23+
```xml
24+
<ItemGroup>
25+
<!-- Be sure to check NuGet for the latest version # -->
26+
<PackageReference Include="JsonApiDotNetCore.OpenApi" Version="4.0.0" />
27+
</ItemGroup>
28+
```
29+
30+
## Usage
31+
32+
Add the integration in your `Startup` class.
33+
34+
```c#
35+
public class Startup
36+
{
37+
public void ConfigureServices(IServiceCollection services)
38+
{
39+
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
40+
services.AddJsonApi<AppDbContext>(mvcBuilder: mvcBuilder);
41+
42+
// Adds the Swashbuckle integration.
43+
services.AddOpenApi(mvcBuilder);
44+
}
45+
46+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
47+
{
48+
app.UseRouting();
49+
app.UseJsonApi();
50+
51+
// Adds the Swashbuckle middleware.
52+
app.UseSwagger();
53+
54+
app.UseEndpoints(endpoints => endpoints.MapControllers());
55+
}
56+
}
57+
```
58+
59+
By default, the OpenAPI specification will be available at `http://localhost:<port>/swagger/v1/swagger.json`.
60+
61+
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 `Startup` class.
62+
63+
```c#
64+
// Startup.cs
65+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
66+
{
67+
app.UseSwaggerUI();
68+
}
69+
```
70+
71+
By default, SwaggerUI will be available at `http://localhost:<port>/swagger`.
72+

docs/usage/toc.md

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
# [Errors](errors.md)
2222
# [Metadata](meta.md)
2323
# [Caching](caching.md)
24+
# [OpenAPI](openapi.md)
2425

2526
# Extensibility
2627
## [Layer Overview](extensibility/layer-overview.md)
@@ -30,3 +31,4 @@
3031
## [Resource Repositories](extensibility/repositories.md)
3132
## [Middleware](extensibility/middleware.md)
3233
## [Query Strings](extensibility/query-strings.md)
34+

src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
<ItemGroup>
77
<ProjectReference Include="..\..\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
8+
<ProjectReference Include="..\..\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
89
</ItemGroup>
910

1011
<ItemGroup>
1112
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
1213
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
14+
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="$(SwashbuckleVersion)" />
1315
</ItemGroup>
1416
</Project>

src/Examples/JsonApiDotNetCoreExample/Startup.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using JsonApiDotNetCore.Configuration;
33
using JsonApiDotNetCore.Diagnostics;
4+
using JsonApiDotNetCore.OpenApi;
45
using JsonApiDotNetCoreExample.Data;
56
using Microsoft.AspNetCore.Authentication;
67
using Microsoft.AspNetCore.Builder;
@@ -44,6 +45,8 @@ public void ConfigureServices(IServiceCollection services)
4445
#endif
4546
});
4647

48+
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
49+
4750
using (CodeTimingSessionManager.Current.Measure("Configure JSON:API (startup)"))
4851
{
4952
services.AddJsonApi<AppDbContext>(options =>
@@ -57,8 +60,10 @@ public void ConfigureServices(IServiceCollection services)
5760
#if DEBUG
5861
options.IncludeExceptionStackTraceInErrors = true;
5962
#endif
60-
}, discovery => discovery.AddCurrentAssembly());
63+
}, discovery => discovery.AddCurrentAssembly(), mvcBuilder: mvcBuilder);
6164
}
65+
66+
services.AddOpenApi(mvcBuilder);
6267
}
6368
}
6469

@@ -82,6 +87,9 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment environment,
8287
app.UseJsonApi();
8388
}
8489

90+
app.UseSwagger();
91+
app.UseSwaggerUI();
92+
8593
app.UseEndpoints(endpoints => endpoints.MapControllers());
8694
}
8795

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<VersionPrefix>$(JsonApiDotNetCoreVersionPrefix)</VersionPrefix>
4+
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
5+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
6+
</PropertyGroup>
7+
8+
<PropertyGroup>
9+
<PackageTags>jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;openapi;swagger;swaggerui;swashbuckle</PackageTags>
10+
<Description>A Swashbuckle integration that enables you to describe a JsonApiDotNetCore API with an OpenAPI specification.</Description>
11+
<Authors>json-api-dotnet</Authors>
12+
<PackageProjectUrl>https://www.jsonapi.net/</PackageProjectUrl>
13+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
14+
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
15+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
16+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
17+
<DebugType>embedded</DebugType>
18+
</PropertyGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
26+
<PrivateAssets>all</PrivateAssets>
27+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
28+
</PackageReference>
29+
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(SwashbuckleVersion)" />
30+
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="$(SwashbuckleVersion)" />
31+
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="$(SwashbuckleVersion)" />
32+
</ItemGroup>
33+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Linq;
2+
using Microsoft.AspNetCore.Mvc.ApplicationModels;
3+
using Microsoft.AspNetCore.Mvc.Routing;
4+
5+
namespace JsonApiDotNetCore.OpenApi
6+
{
7+
internal sealed class OpenApiEndpointConvention : IActionModelConvention
8+
{
9+
public void Apply(ActionModel action)
10+
{
11+
ArgumentGuard.NotNull(action, nameof(action));
12+
13+
if (!action.ActionMethod.GetCustomAttributes(true).OfType<HttpMethodAttribute>().Any())
14+
{
15+
action.ApiExplorer.IsVisible = false;
16+
}
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Swashbuckle.AspNetCore.SwaggerGen;
4+
5+
namespace JsonApiDotNetCore.OpenApi
6+
{
7+
public static class ServiceCollectionExtensions
8+
{
9+
/// <summary>
10+
/// Adds the OpenAPI integration to JsonApiDotNetCore by configuring Swashbuckle.
11+
/// </summary>
12+
public static void AddOpenApi(this IServiceCollection services, IMvcCoreBuilder mvcBuilder, Action<SwaggerGenOptions> setupSwaggerGenAction = null)
13+
{
14+
ArgumentGuard.NotNull(services, nameof(services));
15+
ArgumentGuard.NotNull(mvcBuilder, nameof(mvcBuilder));
16+
17+
mvcBuilder.AddApiExplorer();
18+
19+
mvcBuilder.AddMvcOptions(options => options.Conventions.Add(new OpenApiEndpointConvention()));
20+
21+
services.AddSwaggerGen(setupSwaggerGenAction);
22+
}
23+
}
24+
}

src/JsonApiDotNetCore/JsonApiDotNetCore.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<VersionPrefix>4.2.0</VersionPrefix>
3+
<VersionPrefix>$(JsonApiDotNetCoreVersionPrefix)</VersionPrefix>
44
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
55
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
66
</PropertyGroup>
77

88
<PropertyGroup>
99
<PackageTags>jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net</PackageTags>
1010
<Description>A framework for building JSON:API compliant REST APIs using .NET Core and Entity Framework Core. Includes support for Atomic Operations. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy.</Description>
11+
<Authors>json-api-dotnet</Authors>
1112
<PackageProjectUrl>https://www.jsonapi.net/</PackageProjectUrl>
1213
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1314
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>

src/JsonApiDotNetCore/Properties/AssemblyInfo.cs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Runtime.CompilerServices;
22

3+
[assembly: InternalsVisibleTo("JsonApiDotNetCore.OpenApi")]
34
[assembly: InternalsVisibleTo("Benchmarks")]
45
[assembly: InternalsVisibleTo("JsonApiDotNetCoreTests")]
56
[assembly: InternalsVisibleTo("UnitTests")]

test/OpenApiTests/Airplane.cs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using JetBrains.Annotations;
4+
using JsonApiDotNetCore.Resources;
5+
using JsonApiDotNetCore.Resources.Annotations;
6+
7+
namespace OpenApiTests
8+
{
9+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
10+
public sealed class Airplane : Identifiable
11+
{
12+
[Attr]
13+
public int SeatingCapacity { get; set; }
14+
15+
[Attr]
16+
public DateTimeOffset ManufacturedAt { get; set; }
17+
18+
[HasMany]
19+
public ISet<Flight> Flights { get; set; }
20+
}
21+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using JsonApiDotNetCore.Configuration;
2+
using JsonApiDotNetCore.Controllers;
3+
using JsonApiDotNetCore.Services;
4+
using Microsoft.Extensions.Logging;
5+
6+
namespace OpenApiTests
7+
{
8+
public sealed class AirplanesController : JsonApiController<Airplane>
9+
{
10+
public AirplanesController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<Airplane> resourceService)
11+
: base(options, loggerFactory, resourceService)
12+
{
13+
}
14+
}
15+
}

test/OpenApiTests/Flight.cs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Resources;
4+
using JsonApiDotNetCore.Resources.Annotations;
5+
6+
namespace OpenApiTests
7+
{
8+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
9+
public sealed class Flight : Identifiable
10+
{
11+
[Attr]
12+
public string Destination { get; set; }
13+
14+
[Attr]
15+
public DateTimeOffset DepartsAt { get; set; }
16+
}
17+
}

0 commit comments

Comments
 (0)