CleanResult.Swashbuckle
1.4.2
dotnet add package CleanResult.Swashbuckle --version 1.4.2
NuGet\Install-Package CleanResult.Swashbuckle -Version 1.4.2
<PackageReference Include="CleanResult.Swashbuckle" Version="1.4.2" />
<PackageVersion Include="CleanResult.Swashbuckle" Version="1.4.2" />
<PackageReference Include="CleanResult.Swashbuckle" />
paket add CleanResult.Swashbuckle --version 1.4.2
#r "nuget: CleanResult.Swashbuckle, 1.4.2"
#:package CleanResult.Swashbuckle@1.4.2
#addin nuget:?package=CleanResult.Swashbuckle&version=1.4.2
#tool nuget:?package=CleanResult.Swashbuckle&version=1.4.2
CleanResult.Swashbuckle

<div align="center">
Swagger/OpenAPI integration for CleanResult
Clean OpenAPI documentation by automatically unwrapping Result types
Main Documentation โข Features โข Usage โข Examples
</div>
๐ฆ Installation
dotnet add package CleanResult.Swashbuckle
Requirements:
- .NET 8.0, 9.0, or 10.0
- CleanResult 1.2.8+
- Swashbuckle.AspNetCore 6.0+
โจ Features
- ๐ฏ Automatic Unwrapping - Removes
Result<T>wrapper from OpenAPI schemas - ๐ Clean Documentation - Shows actual return types in Swagger UI
- ๐ HTTP Status Mapping - Correctly maps Result.Ok() to 204, Result<T>.Ok() to 200
- ๐งน Schema Cleanup - Removes Result wrapper schemas from definitions
- โก Zero Configuration - Works automatically after registration
๐ Usage
Registration
Add the CleanResult filters to your Swagger configuration:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSwaggerGen(options =>
{
// โ
Add CleanResult filters - automatically unwraps Result types
options.AddCleanResultFilters();
// Your other Swagger configuration...
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My API",
Version = "v1"
});
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.Run();
What It Does
The filters perform three key transformations:
- Operation Filter - Unwraps Result types in endpoint responses
- Schema Filter - Marks Result wrapper schemas for deletion
- Document Filter - Removes marked schemas from final OpenAPI document
๐ก Examples
Before Integration
Without CleanResult.Swashbuckle, your Swagger documentation shows the Result wrapper:
paths:
/api/users/{id}:
get:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ResultOfUser'
components:
schemas:
ResultOfUser:
type: object
properties:
success: { type: boolean }
successValue: { $ref: '#/components/schemas/User' }
internalErrorValue: { $ref: '#/components/schemas/Error' }
After Integration
With CleanResult.Swashbuckle, documentation is clean and shows actual types:
paths:
/api/users/{id}:
get:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id: { type: integer }
name: { type: string }
email: { type: string }
Controller Examples
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// โ
Swagger shows: 200 OK โ User schema
[HttpGet("{id}")]
public Result<User> GetUser(int id)
{
return Result.Ok(new User { Id = id, Name = "John" });
}
// โ
Swagger shows: 204 No Content
[HttpPost]
public Result CreateUser([FromBody] CreateUserDto dto)
{
return Result.Ok();
}
// โ
Swagger shows: 200 OK โ List<User> schema
[HttpGet]
public Result<List<User>> GetUsers()
{
return Result.Ok(new List<User>());
}
// โ
Swagger shows: 200 OK โ PagedResult<User> schema
[HttpGet("paged")]
public Result<PagedResult<User>> GetPagedUsers([FromQuery] int page = 1)
{
return Result.Ok(new PagedResult<User>());
}
}
Response Status Mapping
The filter correctly maps Result types to HTTP status codes:
| Method Return Type | Swagger Status | Content-Type | Schema |
|---|---|---|---|
Result |
204 No Content | - | None |
Result<User> |
200 OK | application/json | User |
Result<string> |
200 OK | text/plain | string |
Result<byte[]> |
200 OK | application/octet-stream | binary |
Task<Result> |
204 No Content | - | None |
Task<Result<T>> |
200 OK | varies | T |
๐ง How It Works
Three-Phase Filtering
1. Operation Filter (CleanResultReturnTypeFilter)
// Examines controller method return types
// For Result: Changes 200 โ 204 (No Content)
// For Result<T>: Keeps 200 but replaces schema with T's schema
// Unwraps from Task<Result> or Task<Result<T>>
2. Schema Filter (CleanResultSchemaFilter)
// Marks Result type schemas with special title: "SchemaToDelete"
// Prevents Result wrapper types from appearing in schema definitions
3. Document Filter (CleanResultReturnDocumentFilter)
// Final cleanup phase
// Removes all schemas marked "SchemaToDelete"
// Ensures clean OpenAPI document
Architecture
Swagger Generation
โ
Operation Filter
(unwrap types)
โ
Schema Filter
(mark wrappers)
โ
Document Filter
(remove marked)
โ
Clean OpenAPI Doc
๐ฏ Best Practices
โ Do's
// โ
Use Result types directly
[HttpGet("{id}")]
public Result<User> GetUser(int id)
=> _service.GetById(id);
// โ
Works with async
[HttpGet("{id}")]
public async Task<Result<User>> GetUserAsync(int id)
=> await _service.GetByIdAsync(id);
// โ
Complex types are unwrapped correctly
[HttpGet]
public Result<PagedList<UserDto>> GetPagedUsers([FromQuery] PagingParams params)
=> _service.GetPaged(params);
โ Don'ts
// โ Don't wrap Result in IActionResult
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
var result = _service.GetById(id);
return Ok(result); // Bad: Swagger won't unwrap
}
// โ Don't return Result as object
[HttpGet("{id}")]
public object GetUser(int id)
=> _service.GetById(id); // Bad: type information lost
๐ Advanced Configuration
Custom Swagger Options
builder.Services.AddSwaggerGen(options =>
{
// โ
Add CleanResult filters first
options.AddCleanResultFilters();
// Then add your custom configuration
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My API",
Version = "v1",
Description = "API with CleanResult integration"
});
// Add XML comments
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
// Add authorization
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT"
});
});
Response Examples
/// <summary>
/// Gets a user by ID
/// </summary>
/// <param name="id">User ID</param>
/// <returns>The user if found</returns>
/// <response code="200">Returns the user</response>
/// <response code="404">User not found</response>
[HttpGet("{id}")]
[ProducesResponseType(typeof(User), 200)]
[ProducesResponseType(typeof(Error), 404)]
public Result<User> GetUser(int id)
{
var user = _repository.FindById(id);
if (user == null)
return Result<User>.Error("User not found", 404);
return Result.Ok(user);
}
๐ Related Packages
- CleanResult - Core Result implementation
- CleanResult.FluentValidation - FluentValidation integration
- CleanResult.WolverineFx - WolverineFx messaging integration
- CleanResult.AspNet - IActionResult adapter
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
<div align="center">
โฌ Back to Top โข Main Documentation
</div>
<div align="center"> Gwynbleid85 ยฉ 2025 </div>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CleanResult (>= 1.4.2)
- Swashbuckle.AspNetCore.SwaggerGen (>= 10.1.7)
-
net8.0
- CleanResult (>= 1.4.2)
- Swashbuckle.AspNetCore.SwaggerGen (>= 10.1.7)
-
net9.0
- CleanResult (>= 1.4.2)
- Swashbuckle.AspNetCore.SwaggerGen (>= 10.1.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.4.2 | 95 | 5/4/2026 |
| 1.4.1 | 259 | 4/17/2026 |
| 1.4.0 | 117 | 4/16/2026 |
| 1.3.4 | 189 | 1/5/2026 |
| 1.3.3 | 233 | 11/25/2025 |
| 1.3.2 | 1,653 | 11/25/2025 |
| 1.3.1 | 221 | 11/25/2025 |
| 1.3.0 | 505 | 11/4/2025 |
| 1.2.9 | 228 | 10/9/2025 |
| 1.2.8 | 398 | 10/8/2025 |
| 1.2.7 | 507 | 8/25/2025 |
| 1.2.6 | 241 | 8/11/2025 |
| 1.2.5 | 441 | 7/28/2025 |
| 1.2.4 | 553 | 7/24/2025 |
| 1.2.3 | 611 | 7/23/2025 |
| 1.2.2 | 221 | 7/17/2025 |
| 1.2.1 | 211 | 7/17/2025 |