Skip to content

Minimal Swashbuckle setup #1073

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 25 commits into from
Sep 8, 2021
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
11 changes: 11 additions & 0 deletions Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,25 @@ function CreateNuGetPackage {

if ([string]::IsNullOrWhitespace($versionSuffix)) {
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts
}
else {
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$versionSuffix
dotnet pack .\src\JsonApiDotNetCore.OpenApi -c Release -o .\artifacts --version-suffix=$versionSuffix
}

CheckLastExitCode
}

# In a PR the base branch needs to be fetched in order for regitlint to work.
function FetchBaseBranchIfNotMaster(){
if ($env:APPVEYOR_PULL_REQUEST_NUMBER -And $env:APPVEYOR_REPO_BRANCH -ne "master"){
git fetch -q origin ${env:APPVEYOR_REPO_BRANCH}:${env:APPVEYOR_REPO_BRANCH}
}
}

FetchBaseBranchIfNotMaster

dotnet tool restore
CheckLastExitCode

Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<AspNetCoreVersion>5.0.*</AspNetCoreVersion>
<EFCoreVersion>5.0.*</EFCoreVersion>
<NpgsqlPostgreSQLVersion>5.0.*</NpgsqlPostgreSQLVersion>
<SwashbuckleVersion>6.2.*</SwashbuckleVersion>
<JsonApiDotNetCoreVersionPrefix>4.2.0</JsonApiDotNetCoreVersionPrefix>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodingGuidelines.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

Expand Down
30 changes: 30 additions & 0 deletions JsonApiDotNetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextTests", "test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBuildingBlocks", "test\TestBuildingBlocks\TestBuildingBlocks.csproj", "{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonApiDotNetCore.OpenApi", "src\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -210,6 +214,30 @@ Global
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.Build.0 = Release|Any CPU
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.ActiveCfg = Release|Any CPU
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.Build.0 = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU
{B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -228,6 +256,8 @@ Global
{6CAFDDBE-00AB-4784-801B-AB419C3C3A26} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
{EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
{71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
{B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4}
Expand Down
1 change: 1 addition & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ environment:
branches:
only:
- master
- openapi
- develop
- unstable
- /release\/.+/
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/extensibility/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class Startup
{
services.AddSingleton<CustomAsyncQueryStringActionFilter>();

IMvcCoreBuilder builder = services.AddMvcCore();
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
services.AddJsonApi<AppDbContext>(mvcBuilder: builder);

// Ensure this call is placed after the AddJsonApi call.
Expand Down
72 changes: 72 additions & 0 deletions docs/usage/openapi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# OpenAPI

You can describe your API with an OpenAPI specification using the [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) integration for JsonApiDotNetCore.

## Installation

Install the `JsonApiDotNetCore.OpenApi` NuGet package.

### CLI

```
dotnet add package JsonApiDotNetCore.OpenApi
```

### Visual Studio

```powershell
Install-Package JsonApiDotNetCore.OpenApi
```

### *.csproj

```xml
<ItemGroup>
<!-- Be sure to check NuGet for the latest version # -->
<PackageReference Include="JsonApiDotNetCore.OpenApi" Version="4.0.0" />
</ItemGroup>
```

## Usage

Add the integration in your `Startup` class.

```c#
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
IMvcCoreBuilder mvcBuilder = services.AddMvcCore();
services.AddJsonApi<AppDbContext>(mvcBuilder: mvcBuilder);

// Adds the Swashbuckle integration.
services.AddOpenApi(mvcBuilder);
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseJsonApi();

// Adds the Swashbuckle middleware.
app.UseSwagger();

app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
```

By default, the OpenAPI specification will be available at `http://localhost:<port>/swagger/v1/swagger.json`.

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.

```c#
// Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwaggerUI();
}
```

By default, SwaggerUI will be available at `http://localhost:<port>/swagger`.

2 changes: 2 additions & 0 deletions docs/usage/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# [Errors](errors.md)
# [Metadata](meta.md)
# [Caching](caching.md)
# [OpenAPI](openapi.md)

# Extensibility
## [Layer Overview](extensibility/layer-overview.md)
Expand All @@ -30,3 +31,4 @@
## [Resource Repositories](extensibility/repositories.md)
## [Middleware](extensibility/middleware.md)
## [Query Strings](extensibility/query-strings.md)

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

<ItemGroup>
<ProjectReference Include="..\..\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
<ProjectReference Include="..\..\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="$(SwashbuckleVersion)" />
</ItemGroup>
</Project>
10 changes: 9 additions & 1 deletion src/Examples/JsonApiDotNetCoreExample/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Diagnostics;
using JsonApiDotNetCore.OpenApi;
using JsonApiDotNetCoreExample.Data;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
Expand Down Expand Up @@ -44,6 +45,8 @@ public void ConfigureServices(IServiceCollection services)
#endif
});

IMvcCoreBuilder mvcBuilder = services.AddMvcCore();

using (CodeTimingSessionManager.Current.Measure("Configure JSON:API (startup)"))
{
services.AddJsonApi<AppDbContext>(options =>
Expand All @@ -57,8 +60,10 @@ public void ConfigureServices(IServiceCollection services)
#if DEBUG
options.IncludeExceptionStackTraceInErrors = true;
#endif
}, discovery => discovery.AddCurrentAssembly());
}, discovery => discovery.AddCurrentAssembly(), mvcBuilder: mvcBuilder);
}

services.AddOpenApi(mvcBuilder);
}
}

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

app.UseSwagger();
app.UseSwaggerUI();

app.UseEndpoints(endpoints => endpoints.MapControllers());
}

Expand Down
33 changes: 33 additions & 0 deletions src/JsonApiDotNetCore.OpenApi/JsonApiDotNetCore.OpenApi.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>$(JsonApiDotNetCoreVersionPrefix)</VersionPrefix>
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<PropertyGroup>
<PackageTags>jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;openapi;swagger;swaggerui;swashbuckle</PackageTags>
<Description>A Swashbuckle integration that enables you to describe a JsonApiDotNetCore API with an OpenAPI specification.</Description>
<Authors>json-api-dotnet</Authors>
<PackageProjectUrl>https://www.jsonapi.net/</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(SwashbuckleVersion)" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="$(SwashbuckleVersion)" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="$(SwashbuckleVersion)" />
</ItemGroup>
</Project>
19 changes: 19 additions & 0 deletions src/JsonApiDotNetCore.OpenApi/OpenApiEndpointConvention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;

namespace JsonApiDotNetCore.OpenApi
{
internal sealed class OpenApiEndpointConvention : IActionModelConvention
{
public void Apply(ActionModel action)
{
ArgumentGuard.NotNull(action, nameof(action));

if (!action.ActionMethod.GetCustomAttributes(true).OfType<HttpMethodAttribute>().Any())
{
action.ApiExplorer.IsVisible = false;
}
}
}
}
24 changes: 24 additions & 0 deletions src/JsonApiDotNetCore.OpenApi/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace JsonApiDotNetCore.OpenApi
{
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds the OpenAPI integration to JsonApiDotNetCore by configuring Swashbuckle.
/// </summary>
public static void AddOpenApi(this IServiceCollection services, IMvcCoreBuilder mvcBuilder, Action<SwaggerGenOptions> setupSwaggerGenAction = null)
{
ArgumentGuard.NotNull(services, nameof(services));
ArgumentGuard.NotNull(mvcBuilder, nameof(mvcBuilder));

mvcBuilder.AddApiExplorer();

mvcBuilder.AddMvcOptions(options => options.Conventions.Add(new OpenApiEndpointConvention()));

services.AddSwaggerGen(setupSwaggerGenAction);
}
}
}
3 changes: 2 additions & 1 deletion src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>4.2.0</VersionPrefix>
<VersionPrefix>$(JsonApiDotNetCoreVersionPrefix)</VersionPrefix>
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<PropertyGroup>
<PackageTags>jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net</PackageTags>
<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>
<Authors>json-api-dotnet</Authors>
<PackageProjectUrl>https://www.jsonapi.net/</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
Expand Down
1 change: 1 addition & 0 deletions src/JsonApiDotNetCore/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JsonApiDotNetCore.OpenApi")]
[assembly: InternalsVisibleTo("Benchmarks")]
[assembly: InternalsVisibleTo("JsonApiDotNetCoreTests")]
[assembly: InternalsVisibleTo("UnitTests")]
Expand Down
21 changes: 21 additions & 0 deletions test/OpenApiTests/Airplane.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests
{
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
public sealed class Airplane : Identifiable
{
[Attr]
public int SeatingCapacity { get; set; }

[Attr]
public DateTimeOffset ManufacturedAt { get; set; }

[HasMany]
public ISet<Flight> Flights { get; set; }
}
}
15 changes: 15 additions & 0 deletions test/OpenApiTests/AirplanesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Services;
using Microsoft.Extensions.Logging;

namespace OpenApiTests
{
public sealed class AirplanesController : JsonApiController<Airplane>
{
public AirplanesController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<Airplane> resourceService)
: base(options, loggerFactory, resourceService)
{
}
}
}
17 changes: 17 additions & 0 deletions test/OpenApiTests/Flight.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using JetBrains.Annotations;
using JsonApiDotNetCore.Resources;
using JsonApiDotNetCore.Resources.Annotations;

namespace OpenApiTests
{
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
public sealed class Flight : Identifiable
{
[Attr]
public string Destination { get; set; }

[Attr]
public DateTimeOffset DepartsAt { get; set; }
}
}
Loading