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

<div align="center">
IActionResult adapter for CleanResult
Explicit IActionResult conversion for traditional ASP.NET Core controllers
Main Documentation • Features • Usage • When to Use
</div>
📦 Installation
dotnet add package CleanResult.AspNet
Requirements:
- .NET 8.0, 9.0, or 10.0
- ASP.NET Core 8.0+
✨ Features
- 🔄 IActionResult Adapter - Explicit conversion from Result to IActionResult
- 🎯 Controller Compatibility - Works with traditional controller patterns
- ⚡ Zero Overhead - Thin wrapper around existing IResult implementation
- 📄 Clean Integration - Maintains all CleanResult features and behaviors
🚀 Usage
Basic Conversion
using CleanResult.AspNet;
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// ✅ Convert Result to IActionResult
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
var result = _userService.GetById(id);
return result.ToIActionResult();
}
// ✅ Convert Result<T> to IActionResult
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserDto dto)
{
var result = _userService.Create(dto);
return result.ToIActionResult();
}
}
Direct Return Pattern
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
=> _productService.GetById(id).ToIActionResult();
[HttpPut("{id}")]
public IActionResult UpdateProduct(int id, [FromBody] UpdateProductDto dto)
=> _productService.Update(id, dto).ToIActionResult();
[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
=> _productService.Delete(id).ToIActionResult();
}
🤔 When to Use This Package
✅ Use CleanResult.AspNet When
- You're working with existing controllers that return
IActionResult - You need explicit conversion for compatibility
- Your team prefers traditional controller patterns
- You're gradually migrating to CleanResult
// ✅ Good use case: existing IActionResult pattern
public IActionResult GetUser(int id)
{
var result = _service.GetUser(id);
return result.ToIActionResult();
}
❌ Don't Use When
- You're using minimal APIs → Use core CleanResult directly (implements
IResult) - You can return Result types directly → Core CleanResult already implements
IResult
// ❌ Unnecessary - CleanResult already implements IResult
[HttpGet("{id}")]
public Result<User> GetUser(int id) // Direct return works!
=> _service.GetUser(id);
// ❌ Unnecessary conversion
public Result<User> GetUser(int id)
{
var result = _service.GetUser(id);
return result.ToIActionResult(); // Don't do this!
}
💡 Examples
Service Layer Integration
public interface IUserService
{
Result<User> GetById(int id);
Result<User> Create(CreateUserDto dto);
Result Update(int id, UpdateUserDto dto);
Result Delete(int id);
}
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpGet("{id}")]
public IActionResult GetUser(int id){
return _userService.GetById(id).ToIActionResult();
}
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserDto dto){
return _userService.Create(dto).ToIActionResult();
}
[HttpPut("{id}")]
public IActionResult UpdateUser(int id, [FromBody] UpdateUserDto dto){
return _userService.Update(id, dto).ToIActionResult();
}
[HttpDelete("{id}")]
public IActionResult DeleteUser(int id){
return _userService.Delete(id).ToIActionResult();
}
}
Async Patterns
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderService _orderService;
// ✅ Async with IActionResult
[HttpGet("{id}")]
public async Task<IActionResult> GetOrder(int id)
{
var result = await _orderService.GetByIdAsync(id);
return result.ToIActionResult();
}
// ✅ Direct async pattern
[HttpPost]
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderDto dto)
=> (await _orderService.CreateAsync(dto)).ToIActionResult();
}
Error Handling
[ApiController]
[Route("api/[controller]")]
public class PaymentsController : ControllerBase
{
[HttpPost("process")]
public IActionResult ProcessPayment([FromBody] PaymentDto dto)
{
// Service returns Result<PaymentConfirmation>
var result = _paymentService.Process(dto);
// Automatically handles:
// - Success: HTTP 200 with PaymentConfirmation
// - Error: HTTP status from error with Problem Details
return result.ToIActionResult();
}
}
🔧 How It Works
Implementation
The package provides thin wrapper classes that delegate to the underlying IResult implementation:
// For non-generic Result
public static IActionResult ToIActionResult(this Result result)
=> new AspActionResult(result);
// For generic Result<T>
public static IActionResult ToIActionResult<T>(this Result<T> result)
=> new AspActionResult<T>(result);
The wrapper classes implement IActionResult by calling the Result's ExecuteAsync method:
internal class AspActionResult<T> : IActionResult
{
private readonly Result<T> _result;
public Task ExecuteResultAsync(ActionContext context)
=> _result.ExecuteAsync(context.HttpContext);
}
Response Behavior
| Result Type | HTTP Status | Content-Type | Body |
|---|---|---|---|
Result.Ok() |
204 No Content | application/json | Empty |
Result<string>.Ok("text") |
200 OK | text/plain | Raw string |
Result<User>.Ok(user) |
200 OK | application/json | JSON object |
Result<byte[]>.Ok(data) |
200 OK | application/octet-stream | Binary data |
Result.Error("msg", 404) |
404 Not Found | application/json | Problem Details (RFC 9457) |
🎯 Best Practices
✅ Do's
// ✅ Use for existing IActionResult controllers
[HttpGet("{id}")]
public IActionResult GetUser(int id)
=> _service.GetUser(id).ToIActionResult();
// ✅ Use when you need IActionResult explicitly
public IActionResult PerformAction()
{
var result = _service.DoSomething();
if (someCondition)
{
return Redirect("/somewhere");
}
return result.ToIActionResult();
}
// ✅ Consistent with service layer returning Results
public IActionResult ProcessRequest([FromBody] RequestDto dto)
{
var validationResult = _validator.Validate(dto);
if (validationResult.IsError())
return validationResult.ToIActionResult();
return _service.Process(dto).ToIActionResult();
}
❌ Don'ts
// ❌ Don't use when you can return Result directly
[HttpGet("{id}")]
public Result<User> GetUser(int id) // Better: return Result directly
=> _service.GetUser(id).ToIActionResult();
// ❌ Don't double-wrap in IActionResult
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
var result = _service.GetUser(id).ToIActionResult();
return Ok(result); // Bad: unnecessary nesting
}
// ❌ Don't use for minimal APIs
app.MapGet("/users/{id}", (int id) =>
{
var result = _service.GetUser(id);
return result.ToIActionResult(); // Unnecessary - use Result directly
});
🔗 Related Packages
- CleanResult - Core Result implementation
- CleanResult.FluentValidation - FluentValidation integration
- CleanResult.WolverineFx - WolverineFx messaging integration
- CleanResult.Swashbuckle - Swagger/OpenAPI integration
📄 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.3.4)
-
net8.0
- CleanResult (>= 1.3.4)
-
net9.0
- CleanResult (>= 1.3.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.