From ae4d2073c4012d215aa2885626884e41132b6587 Mon Sep 17 00:00:00 2001 From: Polianin Nikita Date: Wed, 25 Dec 2024 07:22:07 +0300 Subject: [PATCH] feat: add a 200 result schema --- .../Core/Startup/SwaggerConfiguration.cs | 1 + .../ActionResultSchemaFilter.cs | 81 +++++++++++++++++++ Endpoint/Controllers/V1/AuthController.cs | 1 - Endpoint/Controllers/V1/ImportController.cs | 5 +- Endpoint/Controllers/V1/SecurityController.cs | 2 +- 5 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 Endpoint/Configuration/SwaggerOptions/ActionResultSchemaFilter.cs diff --git a/Endpoint/Configuration/Core/Startup/SwaggerConfiguration.cs b/Endpoint/Configuration/Core/Startup/SwaggerConfiguration.cs index 0eddcac..8d51276 100644 --- a/Endpoint/Configuration/Core/Startup/SwaggerConfiguration.cs +++ b/Endpoint/Configuration/Core/Startup/SwaggerConfiguration.cs @@ -19,6 +19,7 @@ public static class SwaggerConfiguration { options.SchemaFilter(); options.OperationFilter(); + options.OperationFilter(); var basePath = AppDomain.CurrentDomain.BaseDirectory; options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme diff --git a/Endpoint/Configuration/SwaggerOptions/ActionResultSchemaFilter.cs b/Endpoint/Configuration/SwaggerOptions/ActionResultSchemaFilter.cs new file mode 100644 index 0000000..f1584e2 --- /dev/null +++ b/Endpoint/Configuration/SwaggerOptions/ActionResultSchemaFilter.cs @@ -0,0 +1,81 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Configuration.SwaggerOptions; + +public class ActionResultSchemaFilter : IOperationFilter +{ + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + var returnType = context.MethodInfo.ReturnType; + if (!returnType.IsEquivalentTo(typeof(ActionResult)) && + !returnType.IsEquivalentTo(typeof(ContentResult)) && + !returnType.IsEquivalentTo(typeof(FileStreamResult)) && + !returnType.IsGenericType) + return; + + if (returnType.IsGenericType && + !returnType.GetGenericTypeDefinition().IsEquivalentTo(typeof(ActionResult<>)) && + !returnType.GetGenericTypeDefinition().IsEquivalentTo(typeof(Task<>))) + return; + + var genericType = returnType.IsGenericType ? returnType.GetGenericArguments().FirstOrDefault() : returnType; + if (genericType == null) + return; + + var responseTypeAttributes = context.MethodInfo.GetCustomAttributes(typeof(ProducesResponseTypeAttribute), false) + .Cast() + .Where(attr => attr.StatusCode == 200) + .ToList(); + + var contentType = "application/json"; + + if (context.MethodInfo.GetCustomAttributes(typeof(ProducesAttribute), false) + .FirstOrDefault() is ProducesAttribute producesAttribute) + contentType = producesAttribute.ContentTypes.FirstOrDefault() ?? "application/json"; + + if (responseTypeAttributes.Count != 0) + { + var responseType = responseTypeAttributes.First().Type; + genericType = responseType; + } + + if (genericType.IsEquivalentTo(typeof(ContentResult)) || genericType.IsEquivalentTo(typeof(FileStreamResult))) + { + operation.Responses["200"] = new OpenApiResponse + { + Description = "OK", + Content = new Dictionary + { + [contentType] = new() + } + }; + } + else if (genericType == typeof(ActionResult)) + { + operation.Responses["200"] = new OpenApiResponse { Description = "OK" }; + } + else + { + OpenApiSchema schema; + if (genericType.IsGenericType && genericType.GetGenericTypeDefinition() == typeof(ActionResult<>)) + schema = context.SchemaGenerator.GenerateSchema(genericType.GetGenericArguments().FirstOrDefault(), + context.SchemaRepository); + else + schema = context.SchemaGenerator.GenerateSchema(genericType, context.SchemaRepository); + + operation.Responses["200"] = new OpenApiResponse + { + Description = "OK", + Content = new Dictionary + { + [contentType] = new() { Schema = schema } + } + }; + } + } +} \ No newline at end of file diff --git a/Endpoint/Controllers/V1/AuthController.cs b/Endpoint/Controllers/V1/AuthController.cs index a9ea5a3..0ce1e4d 100644 --- a/Endpoint/Controllers/V1/AuthController.cs +++ b/Endpoint/Controllers/V1/AuthController.cs @@ -48,7 +48,6 @@ public class AuthController(IOptionsSnapshot user, IOptionsSnapshot OAuth2([FromQuery] string code, [FromQuery] string state) diff --git a/Endpoint/Controllers/V1/ImportController.cs b/Endpoint/Controllers/V1/ImportController.cs index a7882e9..7b76fef 100644 --- a/Endpoint/Controllers/V1/ImportController.cs +++ b/Endpoint/Controllers/V1/ImportController.cs @@ -40,7 +40,7 @@ public class ImportController(IMediator mediator, IOptionsSnapshotExcel file [HttpPost("ImportToExcel")] [Produces("application/vnd.ms-excel")] - public async Task ImportToExcel([FromBody] ScheduleRequest request) + public async Task ImportToExcel([FromBody] ScheduleRequest request) { var result = (await mediator.Send(new GetScheduleListQuery { @@ -51,9 +51,6 @@ public class ImportController(IMediator mediator, IOptionsSnapshot generalConfig) : [HttpGet("GenerateTotpQrCode")] [Produces("image/svg+xml")] [MaintenanceModeIgnore] - public IActionResult GenerateTotpQrCode( + public ContentResult GenerateTotpQrCode( [FromQuery] string totpKey, [FromQuery] string label, [FromQuery] string? backgroundColor = null,