Swagger - artemovsergey/ASP GitHub Wiki

Package

  <ItemGroup>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.2" />
    <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="8.1.1" />
    <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
  </ItemGroup>

Swagger Services

public static class SwaggerServices
{
    public static IServiceCollection AddSwaggerServices(
        this IServiceCollection services
    )
    {
        services.AddOpenApi();
        
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc(
                "v1",
                new OpenApiInfo
                {
                    Title = "Крестики-нолики",
                    Version = "v1",
                    Description = "API для пользователей",
                    Contact = new OpenApiContact
                    {
                        Url = new Uri("https://github.com/artemovsergey/TicTacToe"),
                        Email = "[email protected]",
                    }
                }
            );

            c.EnableAnnotations();
            c.SchemaFilter<ErrorResponseSchemaFilter>();
            c.OperationFilter<ErrorResponseOperationFilter>();
        });

        return services;
    }
}

Swagger Middlewares

public static class SwaggerMiddlewares
{
    public static WebApplication UseSwaggerMiddleware(this WebApplication app)
    {
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "Крестики-Нолики API");
            c.RoutePrefix = string.Empty;
        });
        
        app.MapOpenApi();
        
        return app;
    }
}

Filters

// Фильтр для добавления примеров ErrorResponse
public class ErrorResponseSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type == typeof(ErrorResponse))
        {
            schema.Example = new OpenApiObject
            {
                ["statusCode"] = new OpenApiString("400"),
                ["message"] = new OpenApiString("Invalid request"),
                ["detail"] = new OpenApiString("The 'id' parameter must be a positive number")
            };
        }
    }
}


public class ErrorResponseOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var statusCodes = new Dictionary<string, (string Message, string Detail)>
        {
            ["400"] = ("Invalid request", "The 'id' parameter must be a positive number"),
            ["404"] = ("Resource not found", "The requested resource was not found"),
            ["409"] = ("Conflict", "Поле занято"),
            ["412"] = ("Precondition failed", "Несогласованное состояние объекта Game"),
            ["500"] = ("Internal server error", "An unexpected error occurred")
        };

        foreach (var (code, (message, detail)) in statusCodes)
        {
            if (operation.Responses.TryGetValue(code, out var response) &&
                response.Content.TryGetValue("application/json", out var mediaType))
            {
                mediaType.Example = new OpenApiObject
                {
                    ["statusCode"] = new OpenApiInteger(int.Parse(code)),
                    ["message"] = new OpenApiString(message),
                    ["detail"] = new OpenApiString(detail)
                };
            }
        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️