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 6 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
9 changes: 5 additions & 4 deletions Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,14 @@ function CreateNuGetPackage {
CheckLastExitCode
}

function LoadBaseBranchIfNotMaster(){
if ($env:APPVEYOR_REPO_BRANCH -ne "master") {
git fetch origin ${env:APPVEYOR_REPO_BRANCH}:${env:APPVEYOR_REPO_BRANCH}
# 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}
}
}

LoadBaseBranchIfNotMaster
FetchBaseBranchIfNotMaster

dotnet tool restore
CheckLastExitCode
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ Install-Package JsonApiDotnetCore
```xml
<ItemGroup>
<!-- Be sure to check NuGet for the latest version # -->
<PackageReference Include="JsonApiDotNetCore" Version="4.0.0" />
<PackageReference Include="JsonApiDotnetCore" Version="4.0.0" />
</ItemGroup>
```
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 builder = services.AddMvcCore();
services.AddJsonApi<AppDbContext>(mvcBuilder: builder);

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

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 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 @@ -30,3 +30,5 @@
## [Resource Repositories](extensibility/repositories.md)
## [Middleware](extensibility/middleware.md)
## [Query Strings](extensibility/query-strings.md)

# [OpenAPI](openapi.md)
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
<ProjectReference Include="..\..\JsonApiDotNetCore\JsonApiDotNetCore.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>
1 change: 0 additions & 1 deletion src/Examples/JsonApiDotNetCoreExample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using JsonApiDotNetCoreExample.Startups;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

Expand Down
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 All @@ -12,7 +13,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace JsonApiDotNetCoreExample.Startups
namespace JsonApiDotNetCoreExample
{
public sealed class Startup
{
Expand Down Expand Up @@ -44,6 +45,10 @@ public void ConfigureServices(IServiceCollection services)
#endif
});

IMvcCoreBuilder mvcCoreBuilder = services.AddMvcCore();

services.AddOpenApi(mvcCoreBuilder);

using (CodeTimingSessionManager.Current.Measure("Configure JSON:API (startup)"))
{
services.AddJsonApi<AppDbContext>(options =>
Expand All @@ -57,7 +62,7 @@ public void ConfigureServices(IServiceCollection services)
#if DEBUG
options.IncludeExceptionStackTraceInErrors = true;
#endif
}, discovery => discovery.AddCurrentAssembly());
}, discovery => discovery.AddCurrentAssembly(), mvcBuilder: mvcCoreBuilder);
}
}
}
Expand All @@ -77,6 +82,9 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment environment,

app.UseRouting();

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

using (CodeTimingSessionManager.Current.Measure("Initialize JSON:API (startup)"))
{
app.UseJsonApi();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace JsonApiDotNetCore.OpenApi
{
public static class ServiceCollectionExtensions
{
public static void AddOpenApi(this IServiceCollection services, IMvcCoreBuilder builder, Action<SwaggerGenOptions> setupSwaggerGenAction)
public static void AddOpenApi(this IServiceCollection services, IMvcCoreBuilder builder, Action<SwaggerGenOptions> setupSwaggerGenAction = null)
{
ArgumentGuard.NotNull(services, nameof(services));
ArgumentGuard.NotNull(builder, nameof(builder));
Expand Down
2 changes: 1 addition & 1 deletion test/OpenApiTests/AirplanesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace OpenApiTests
{
public sealed class AirplanesController : JsonApiController<Airplane>
{
public AirplanesController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<Airplane, int> resourceService)
public AirplanesController(IJsonApiOptions options, ILoggerFactory loggerFactory, IResourceService<Airplane> resourceService)
: base(options, loggerFactory, resourceService)
{
}
Expand Down
9 changes: 0 additions & 9 deletions test/OpenApiTests/OpenApiDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;

// @formatter:wrap_chained_method_calls chop_always
// @formatter:keep_existing_linebreaks true

namespace OpenApiTests
{
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
Expand All @@ -16,11 +13,5 @@ public OpenApiDbContext(DbContextOptions<OpenApiDbContext> options)
: base(options)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Airplane>()
.HasMany(airplane => airplane.Flights);
}
}
}
4 changes: 2 additions & 2 deletions test/OpenApiTests/OpenApiDocumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ public OpenApiDocumentTests()
}

[Fact]
public async Task Retrieved_document_should_match_expected_document()
public async Task Retrieved_document_matches_expected_document()
{
// Arrange
string embeddedResourceName = $"{nameof(OpenApiTests)}.openapi.json";
string expectedDocument = await LoadEmbeddedResourceAsync(embeddedResourceName);
string requestUrl = $"swagger/{nameof(OpenApiTests)}/swagger.json";
string requestUrl = $"swagger/{OpenApiStartup<OpenApiDbContext>.OpenApiDocumentName}/swagger.json";

// Act
string actualDocument = await GetAsync(requestUrl);
Expand Down
9 changes: 4 additions & 5 deletions test/OpenApiTests/OpenApiStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,26 @@ namespace OpenApiTests
public sealed class OpenApiStartup<TDbContext> : TestableStartup<TDbContext>
where TDbContext : DbContext
{
internal const string OpenApiDocumentName = nameof(OpenApiTests);

public override void ConfigureServices(IServiceCollection services)
{
IMvcCoreBuilder mvcCoreBuilder = services.AddMvcCore();

services.AddJsonApi<TDbContext>(SetJsonApiOptions, mvcBuilder: mvcCoreBuilder);

services.AddOpenApi(mvcCoreBuilder, options => options.SwaggerDoc(nameof(OpenApiTests), new OpenApiInfo
services.AddOpenApi(mvcCoreBuilder, options => options.SwaggerDoc(OpenApiDocumentName, new OpenApiInfo
{
Title = nameof(OpenApiTests),
Title = OpenApiDocumentName,
Version = "1"
}));
}

public override void Configure(IApplicationBuilder app, IWebHostEnvironment environment, ILoggerFactory loggerFactory)
{
app.UseRouting();

app.UseJsonApi();

app.UseSwagger();

app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
Expand Down
48 changes: 21 additions & 27 deletions test/OpenApiTests/OpenApiTests.csproj
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>$(NetCoreAppVersion)</TargetFramework>
</PropertyGroup>

<ItemGroup>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
<ProjectReference Include="..\TestBuildingBlocks\TestBuildingBlocks.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\JsonApiDotNetCore.OpenApi\JsonApiDotNetCore.OpenApi.csproj" />
<ProjectReference Include="..\TestBuildingBlocks\TestBuildingBlocks.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="$(CoverletVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="$(CoverletVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="openapi.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="openapi.json" />
</ItemGroup>

<!-- Fixes IntelliSense errors on openapi.json in Visual Studio 2019, which uses the schema for OpenAPI 3.1 by default. -->
<ProjectExtensions>
<VisualStudio>
<UserProperties openapi_1json__JsonSchema="https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json" />
</VisualStudio>
</ProjectExtensions>
<!-- Fixes IntelliSense errors on openapi.json in Visual Studio 2019, which uses the schema for OpenAPI 3.1 by default. -->
<ProjectExtensions>
<VisualStudio>
<UserProperties integrationtests_4openapi_1json__JsonSchema="https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json" />
</VisualStudio>
</ProjectExtensions>
</Project>