Skip to content

Commit

Permalink
refactor: ♻️ refactor to use .net 9 openapi generator
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdihadeli committed Dec 18, 2024
1 parent 379a5f4 commit 5dec3ec
Show file tree
Hide file tree
Showing 43 changed files with 888 additions and 299 deletions.
10 changes: 9 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,10 @@ dotnet_diagnostic.ca1848.severity = Suggestion
dotnet_diagnostic.ca1810.severity = Suggestion
# CA1725: Parameter names should match base declaration
dotnet_diagnostic.ca1725.severity = Suggestion

# CA1515: Consider making public types internal
dotnet_diagnostic.CA1515.severity = Suggestion
# CA2000: Dispose objects before losing scope
dotnet_diagnostic.CA2000.severity = Suggestion

##################################################################################
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
Expand All @@ -233,6 +235,9 @@ dotnet_diagnostic.IDE0051.severity = Suggestion
# IDE0052: Remove unread private members (writes but no reads)
dotnet_diagnostic.IDE0052.severity = error

# Remove unnecessary using directives (IDE0005)
dotnet_diagnostic.IDE0005.severity = none

# CS1574: XML comment on 'construct' has syntactically incorrect cref attribute 'name'
dotnet_diagnostic.CS1574.severity = error

Expand Down Expand Up @@ -695,6 +700,9 @@ dotnet_diagnostic.vsthrd200.severity = Suggestion
# VSTHRD200: Use "Async" suffix for async methods
dotnet_diagnostic.vsthrd200.severity = Suggestion

# VSTHRD003 Avoid awaiting foreign Tasks
dotnet_diagnostic.VSTHRD003.severity = Suggestion


##################################################################################
## https://github.com/hvanbakel/Asyncify-CSharp
Expand Down
5 changes: 1 addition & 4 deletions src/ApiClients/ApiClients.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,5 @@
<Options>/ClassStyle:Record /DateTimeType:System.DateTime /UseBaseUrl:false /GenerateBaseUrlProperty:true /ExceptionClass:ApiException /GenerateClientInterfaces:true</Options>
</OpenApiReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Clients\" />
</ItemGroup>


</Project>
39 changes: 4 additions & 35 deletions src/App/Vertical.Slice.Template.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using Scalar.AspNetCore;
using Serilog;
using Serilog.Events;
using Shared.Logging.Extensions;
using Shared.Swagger;
using Shared.Web.Extensions;
using Shared.Web.Minimal.Extensions;
using Vertical.Slice.Template.Shared;
using Vertical.Slice.Template.Shared.Extensions.WebApplicationBuilderExtensions;
using Vertical.Slice.Template.Shared.Extensions.WebApplicationExtensions;

// https://github.com/serilog/serilog-aspnetcore#two-stage-initialization
// https://github.com/serilog/serilog-extensions-hosting
Expand All @@ -20,10 +18,6 @@
{
var builder = WebApplication.CreateBuilder(args);

builder.AddCustomSerilog();

builder.AddAppProblemDetails();

builder.Host.UseDefaultServiceProvider(
(context, options) =>
{
Expand All @@ -46,6 +40,8 @@
}
);

builder.AddInfrastructures();

builder.AddCatalogsServices();

var app = builder.Build();
Expand All @@ -55,41 +51,14 @@
return;
}

// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling
// https://github.com/dotnet/aspnetcore/pull/26567
app.UseExceptionHandler(options: new ExceptionHandlerOptions { AllowStatusCode404Response = true });

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment() || app.Environment.IsTest())
{
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/handle-errrors
app.UseDeveloperExceptionPage();
}

// this middleware should be first middleware
// request logging just log in information level and above as default
app.UseSerilogRequestLogging();
await app.UseInfrastructure();

await app.UseCatalogs();

app.MapCatalogsEndpoints();

app.MapModulesEndpoints();

// #if EnableSwagger
if (app.Environment.IsDevelopment())
{
// should register as last middleware for discovering all endpoints and its versions correctly
app.UseCustomSwagger();

// https://github.com/scalar/scalar/blob/main/packages/scalar.aspnetcore/README.md
app.MapScalarApiReference(redocOptions =>
{
redocOptions.WithOpenApiRoutePattern("/swagger/{documentName}/swagger.json");
});
}

// #endif
await app.RunAsync();
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,26 @@
<ItemGroup>
<ProjectReference Include="..\Vertical.Slice.Template\Vertical.Slice.Template.csproj"/>
</ItemGroup>

<!-- &lt;!&ndash; Issue: Right now for generate build time openapi we should add `AddOpenApi` in Program.cs not in another assembly as infrastructure reference&ndash;&gt;-->
<!-- <PropertyGroup>-->
<!-- <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>-->
<!-- <OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>-->
<!-- <OpenApiGenerateDocumentsOnBuild>true</OpenApiGenerateDocumentsOnBuild>-->
<!-- </PropertyGroup>-->
<!-- <ItemGroup>-->
<!-- <PackageReference Include="Microsoft.AspNetCore.OpenApi" />-->
<!-- &lt;!&ndash; https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi?view=aspnetcore-9.0&tabs=visual-studio#generate-openapi-documents-at-build-time&ndash;&gt;-->
<!-- <PackageReference Include="Microsoft.Extensions.ApiDescription.Server">-->
<!-- <PrivateAssets>all</PrivateAssets>-->
<!-- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
<!-- </PackageReference>-->
<!-- </ItemGroup>-->

<!-- &lt;!&ndash; Generate swagger.json in build time&ndash;&gt;-->
<!-- &lt;!&ndash; https://github.com/domaindrivendev/Swashbuckle.AspNetCore?tab=readme-ov-file#swashbuckleaspnetcorecli&ndash;&gt;-->
<!-- <Target Name="GenerateSwagger" AfterTargets="Build">-->
<!-- <Exec Command="dotnet swagger tofile &#45;&#45;output $(OutputPath)swagger.json $(TargetPath)" />-->
<!-- </Target>-->

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Microsoft.AspNetCore.Routing;
using Shared.Abstractions.Web;
using Shared.Core.Extensions;
using Shared.Web.Minimal.Extensions;
using Shared.Web.ProblemDetail.HttpResults;

namespace Vertical.Slice.Template.Products.Features.CreatingProduct.v1;
Expand All @@ -24,7 +23,8 @@ internal static RouteHandlerBuilder MapCreateProductEndpoint(this IEndpointRoute
return app.MapPost("/", Handle)
.WithName(nameof(CreateProduct))
.WithDisplayName(nameof(CreateProduct).Humanize())
.WithSummaryAndDescription(nameof(CreateProduct).Humanize(), nameof(CreateProduct).Humanize())
.WithSummary(nameof(CreateProduct).Humanize())
.WithDescription(nameof(CreateProduct).Humanize())
.WithTags(ProductConfigurations.Tag)
.MapToApiVersion(1.0);
// .Produces<CreateProductResponse>("Product created successfully.", StatusCodes.Status201Created)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Shared.Abstractions.Web;
using Shared.Web.Minimal.Extensions;
using Shared.Web.ProblemDetail.HttpResults;
using Vertical.Slice.Template.Products.Dtos.v1;

Expand All @@ -20,7 +19,8 @@ internal static RouteHandlerBuilder MapGetProductByIdEndpoint(this IEndpointRout
return app.MapGet("/{id:guid}", Handle)
.WithName(nameof(GetProductById))
.WithDisplayName(nameof(GetProductById).Humanize())
.WithSummaryAndDescription(nameof(GetProductById).Humanize(), nameof(GetProductById).Humanize())
.WithSummary(nameof(GetProductById).Humanize())
.WithDescription(nameof(GetProductById).Humanize())
.WithTags(ProductConfigurations.Tag)
.MapToApiVersion(1.0);
// .Produces<GetProductByIdResponse>("Product fetched successfully.", StatusCodes.Status200OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.AspNetCore.Routing;
using Shared.Abstractions.Core.Paging;
using Shared.Abstractions.Web;
using Shared.Web.Minimal.Extensions;
using Vertical.Slice.Template.Products.Dtos.v1;

namespace Vertical.Slice.Template.Products.Features.GettingProductsByPage.v1;
Expand All @@ -19,7 +18,8 @@ internal static RouteHandlerBuilder MapGetProductsByPageEndpoint(this IEndpointR
return app.MapGet("/", Handle)
.WithName(nameof(GetProductsByPage))
.WithDisplayName(nameof(GetProductsByPage).Humanize())
.WithSummaryAndDescription(nameof(GetProductsByPage).Humanize(), nameof(GetProductsByPage).Humanize())
.WithSummary(nameof(GetProductsByPage).Humanize())
.WithDescription(nameof(GetProductsByPage).Humanize())
.WithTags(ProductConfigurations.Tag)
.MapToApiVersion(1.0);
// .Produces<GetProductsByPageResponse>("Products fetched successfully.", StatusCodes.Status200OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Microsoft.AspNetCore.Routing;
using Vertical.Slice.Template.Products;
using Vertical.Slice.Template.Shared.Extensions.WebApplicationBuilderExtensions;
using Vertical.Slice.Template.Shared.Extensions.WebApplicationExtensions;
using Vertical.Slice.Template.Users;

namespace Vertical.Slice.Template.Shared;
Expand All @@ -14,11 +13,6 @@ public static class CatalogsConfigurations

public static WebApplicationBuilder AddCatalogsServices(this WebApplicationBuilder builder)
{
// Shared
// Infrastructure
builder.AddInfrastructures();

// Shared
// Catalogs Configurations
builder.AddStorage();

Expand All @@ -31,9 +25,6 @@ public static WebApplicationBuilder AddCatalogsServices(this WebApplicationBuild

public static async Task<WebApplication> UseCatalogs(this WebApplication app)
{
// Shared
await app.UseInfrastructure();

// Modules
await app.UseProductsModule();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Shared.Abstractions.Persistence;
using Shared.Abstractions.Persistence.Ef;

namespace Vertical.Slice.Template.Shared.Data;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Reflection;
using CorrelationId.DependencyInjection;
using Mediator;
using Microsoft.AspNetCore.Builder;
Expand All @@ -7,7 +8,9 @@
using Shared.Core.Extensions;
using Shared.EF;
using Shared.Logging;
using Shared.Swagger;
using Shared.Logging.Extensions;
using Shared.OpenApi.AspnetOpenApi.Extensions;
using Shared.OpenApi.Swashbuckle.Extensions;
using Shared.Validation;
using Shared.Validation.Extensions;
using Shared.Web.Extensions;
Expand All @@ -20,6 +23,10 @@ public static partial class WebApplicationBuilderExtensions
{
public static WebApplicationBuilder AddInfrastructures(this WebApplicationBuilder builder)
{
builder.AddCustomSerilog();

builder.AddAppProblemDetails();

builder.Services.AddCore();

// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/security
Expand All @@ -32,8 +39,7 @@ public static WebApplicationBuilder AddInfrastructures(this WebApplicationBuilde
builder.Services.AddDefaultCorrelationId();

// #if EnableSwagger
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.AddCustomSwagger();
builder.AddAspnetOpenApi();
// #endif

builder.AddCustomVersioning();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using CorrelationId;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Serilog;
using Shared.OpenApi.AspnetOpenApi.Extensions;
using Shared.Web.Extensions;

namespace Vertical.Slice.Template.Shared.Extensions.WebApplicationExtensions;
Expand All @@ -8,6 +11,21 @@ public static partial class WebApplicationExtensions
{
public static Task UseInfrastructure(this WebApplication app)
{
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling
// https://github.com/dotnet/aspnetcore/pull/26567
app.UseExceptionHandler(options: new ExceptionHandlerOptions { AllowStatusCode404Response = true });

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment() || app.Environment.IsTest())
{
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/handle-errrors
app.UseDeveloperExceptionPage();
}

// this middleware should be first middleware
// request logging just log in information level and above as default
app.UseSerilogRequestLogging();

app.UseCustomCors();

// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/security
Expand All @@ -17,6 +35,13 @@ public static Task UseInfrastructure(this WebApplication app)
// https://github.com/stevejgordon/CorrelationId
app.UseCorrelationId();

// #if EnableSwagger
if (app.Environment.IsDevelopment())
{
app.UseAspnetOpenApi();
}
// #endif

return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ internal static RouteHandlerBuilder MapGetUsersByPageEndpoint(this IEndpointRout
return app.MapGet("/", Handle)
.WithName(nameof(GetUsersByPageEndpoint))
.WithDisplayName(nameof(GetUsersByPageEndpoint).Humanize())
.WithSummaryAndDescription(
nameof(GetUsersByPageEndpoint).Humanize(),
nameof(GetUsersByPageEndpoint).Humanize()
)
.WithSummary(nameof(GetUsersByPageEndpoint).Humanize())
.WithDescription(nameof(GetUsersByPageEndpoint).Humanize())
.WithTags(UsersConfigurations.Tag)
.MapToApiVersion(1.0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,5 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<Folder Include="Shared\Data\Migrations\Catalogs\" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<PackageVersion Include="System.Net.Http.Json" Version="9.0.0" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageVersion Include="EFCore.NamingConventions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
Expand Down Expand Up @@ -52,6 +53,8 @@
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Linq.Async.Queryable" Version="6.0.1" />
<PackageVersion Include="NSwag.ApiDescription.Client" Version="14.2.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Shared.Abstractions.Persistence.Ef;
namespace Shared.Abstractions.Persistence;

public interface IDataSeeder
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static IServiceCollection AddCore(this IServiceCollection services, param

services.AddScoped<ISieveProcessor, ApplicationSieveProcessor>();

services.AddPersistenceCore(assemblies);
services.AddPersistenceCore();

services.AddValidatedOptions<PolicyOptions>(nameof(PolicyOptions));

Expand Down
19 changes: 19 additions & 0 deletions src/Shared/Core/Persistence/DataSeedWorker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.Extensions.Hosting;
using Shared.Abstractions.Persistence;

namespace Shared.Core.Persistence;

// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services
// Here we use `IHostedService` instead of `BackgroundService` because we want to have control for running async task in StartAsync method and wait for completion not running it in background like `BackgroundService` in its StartAsync
public class DataSeedWorker(IDataSeederManager dataSeederManager) : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
await dataSeederManager.ExecuteAsync(cancellationToken);
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Loading

0 comments on commit 5dec3ec

Please sign in to comment.