Refactor: Rename DocumentOperator to DocumentService
Updated project and solution files to rename and restructure `DocumentOperator` to `DocumentService`. Modified project references in `DocumentService.API.csproj`, `DocumentService.Application.csproj`, and `DocumentService.Infrastructure.csproj` to reflect the new naming convention. Updated `DocumentService.sln` to remove old project references, add new ones, and adjust configuration and nested project mappings accordingly. This change aligns the project structure with the new naming convention.
This commit is contained in:
125
DocumentService.API/Configuration/DualInputDocumentFilter.cs
Normal file
125
DocumentService.API/Configuration/DualInputDocumentFilter.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace DocumentService.API.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Swagger document filter that merges operations with same path but different [Consumes] attributes.
|
||||
/// Ensures both multipart/form-data and application/json variants are visible in Swagger UI.
|
||||
/// </summary>
|
||||
public class DualInputDocumentFilter : IDocumentFilter
|
||||
{
|
||||
private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DualInputDocumentFilter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="apiDescriptionProvider">API description provider to access all endpoints</param>
|
||||
public DualInputDocumentFilter(IApiDescriptionGroupCollectionProvider apiDescriptionProvider)
|
||||
{
|
||||
_apiDescriptionProvider = apiDescriptionProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the filter to merge operations with different content types.
|
||||
/// </summary>
|
||||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
||||
{
|
||||
var allApiDescriptions = _apiDescriptionProvider.ApiDescriptionGroups.Items
|
||||
.SelectMany(g => g.Items)
|
||||
.ToList();
|
||||
|
||||
// Group by path
|
||||
var groupedByPath = allApiDescriptions
|
||||
.GroupBy(x => "/" + x.RelativePath)
|
||||
.ToList();
|
||||
|
||||
foreach (var group in groupedByPath)
|
||||
{
|
||||
var path = group.Key;
|
||||
|
||||
if (!swaggerDoc.Paths.ContainsKey(path))
|
||||
continue;
|
||||
|
||||
var pathItem = swaggerDoc.Paths[path];
|
||||
|
||||
// Find multipart and JSON variants
|
||||
var multipartDesc = group.FirstOrDefault(x =>
|
||||
x.SupportedRequestFormats.Any(f => f.MediaType == "multipart/form-data"));
|
||||
|
||||
var jsonDesc = group.FirstOrDefault(x =>
|
||||
x.SupportedRequestFormats.Any(f => f.MediaType == "application/json"));
|
||||
|
||||
// If we have both variants, merge them into single operation
|
||||
if (multipartDesc != null && jsonDesc != null)
|
||||
{
|
||||
var httpMethod = multipartDesc.HttpMethod?.ToLowerInvariant();
|
||||
OperationType operationType;
|
||||
|
||||
if (!Enum.TryParse<OperationType>(httpMethod, true, out operationType))
|
||||
continue;
|
||||
|
||||
if (!pathItem.Operations.ContainsKey(operationType))
|
||||
continue;
|
||||
|
||||
var operation = pathItem.Operations[operationType];
|
||||
|
||||
// Ensure RequestBody exists
|
||||
if (operation.RequestBody == null)
|
||||
{
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Content = new Dictionary<string, OpenApiMediaType>()
|
||||
};
|
||||
}
|
||||
|
||||
// Add multipart/form-data if missing
|
||||
if (!operation.RequestBody.Content.ContainsKey("multipart/form-data"))
|
||||
{
|
||||
operation.RequestBody.Content.Add("multipart/form-data", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
["file"] = new OpenApiSchema
|
||||
{
|
||||
Type = "string",
|
||||
Format = "binary",
|
||||
Description = "PDF file to upload"
|
||||
}
|
||||
},
|
||||
Required = new HashSet<string> { "file" }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add application/json if missing
|
||||
if (!operation.RequestBody.Content.ContainsKey("application/json"))
|
||||
{
|
||||
operation.RequestBody.Content.Add("application/json", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
["base64Pdf"] = new OpenApiSchema
|
||||
{
|
||||
Type = "string",
|
||||
Format = "byte",
|
||||
Description = "Base64-encoded PDF file content"
|
||||
}
|
||||
},
|
||||
Required = new HashSet<string> { "base64Pdf" }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user