Table of Contents

Class ActionResultExtensionsAsync

Namespace
FunctionalDdd
Assembly
FunctionalDdd.Asp.dll

Provides asynchronous extension methods to convert Task/ValueTask-wrapped Result types to ASP.NET Core ActionResult responses. These methods enable clean async/await patterns in controllers while maintaining Railway Oriented Programming benefits.

public static class ActionResultExtensionsAsync
Inheritance
ActionResultExtensionsAsync
Inherited Members

Remarks

These extensions are async variants of ActionResultExtensions, designed for use with async service methods. They support both Task<TResult> and ValueTask<TResult> for maximum flexibility and performance.

Key benefits:

  • Clean async controller code without manual awaiting
  • Automatic HTTP status code selection based on error type
  • Support for both Task and ValueTask for performance optimization
  • Consistent error handling across async operations
  • Seamless integration with async Railway Oriented Programming chains

Usage pattern in async controllers (with CancellationToken):

public class UsersController : ControllerBase
{
    [HttpGet("{id}")]
    public Task<ActionResult<UserDto>> GetUserAsync(string id, CancellationToken ct) =>
        UserId.TryCreate(id)
            .BindAsync(userId => _userService.GetUserAsync(userId, ct))
            .MapAsync(user => new UserDto(user))
            .ToActionResultAsync(this);
}

Best Practice: Always accept a CancellationToken parameter in async controller methods and pass it through to all async service calls. This enables proper request cancellation, graceful shutdown, and timeout handling.

Methods

ToActionResultAsync<TValue>(Task<Result<TValue>>, ControllerBase)

Converts a Task-wrapped Result<TValue> to an ActionResult<TValue> with appropriate HTTP status code.

public static Task<ActionResult<TValue>> ToActionResultAsync<TValue>(this Task<Result<TValue>> resultTask, ControllerBase controllerBase)

Parameters

resultTask Task<Result<TValue>>

The task containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

Returns

Task<ActionResult<TValue>>

A task that represents the asynchronous operation, containing:

  • 200 OK with value if result is successful (except for Unit)
  • 204 No Content if result is successful and TValue is Unit
  • Appropriate error status code (400-599) based on error type if result is failure

Type Parameters

TValue

The type of the value contained in the result.

Examples

Async GET endpoint with database query and CancellationToken:

[HttpGet("{id}")]
public Task<ActionResult<UserDto>> GetUserAsync(Guid id, CancellationToken ct) =>
    UserId.TryCreate(id)
        .BindAsync(userId => _repository.GetByIdAsync(userId, ct))
        .MapAsync(user => new UserDto(user))
        .ToActionResultAsync(this);

// Success: 200 OK with UserDto
// Not found: 404 Not Found with Problem Details

Async POST endpoint with multiple operations and CancellationToken:

[HttpPost]
public Task<ActionResult<OrderDto>> CreateOrderAsync(
    CreateOrderRequest request,
    CancellationToken ct) =>
    CustomerId.TryCreate(request.CustomerId)
        .BindAsync(customerId => _customerService.GetCustomerAsync(customerId, ct))
        .BindAsync(customer => _orderService.CreateOrderAsync(customer, request.Items, ct))
        .TapAsync(order => _eventBus.PublishAsync(new OrderCreatedEvent(order.Id), ct))
        .MapAsync(order => new OrderDto(order))
        .ToActionResultAsync(this);

// Success: 200 OK with OrderDto
// Validation error: 400 Bad Request
// Customer not found: 404 Not Found

Remarks

This is the primary async method for converting domain results to HTTP responses. It awaits the result task and delegates to ToActionResult<TValue>(Result<TValue>, ControllerBase).

For performance-critical scenarios where the operation frequently completes synchronously, consider using the ValueTask overload instead.

CancellationToken Best Practice: The controller method should accept a CancellationToken parameter (ASP.NET Core automatically provides request cancellation) and pass it to all async service calls in the chain.

ToActionResultAsync<TValue>(Task<Result<TValue>>, ControllerBase, long, long, long)

Converts a Task-wrapped Result<TValue> to an ActionResult<TValue> with support for partial content responses using explicit range values.

public static Task<ActionResult<TValue>> ToActionResultAsync<TValue>(this Task<Result<TValue>> resultTask, ControllerBase controllerBase, long from, long to, long totalLength)

Parameters

resultTask Task<Result<TValue>>

The task containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

from long

The starting index of the range (inclusive, 0-based).

to long

The ending index of the range (inclusive, 0-based).

totalLength long

The total number of items available.

Returns

Task<ActionResult<TValue>>

A task that represents the asynchronous operation, containing:

  • 206 Partial Content with Content-Range header if the range is a subset of the total
  • 200 OK if the range represents the complete set
  • Appropriate error status code if result is failure

Type Parameters

TValue

The type of the value contained in the result.

Examples

[HttpGet]
public async Task<ActionResult<IEnumerable<UserDto>>> GetUsersAsync(
    [FromQuery] int page = 0,
    [FromQuery] int pageSize = 25)
{
    var from = page * pageSize;
    var to = from + pageSize - 1;

    var totalCount = await _userService.GetTotalCountAsync();

    return await _userService
        .GetUsersAsync(from, pageSize)
        .MapAsync(users => users.Select(u => new UserDto(u)))
        .ToActionResultAsync(this, from, to, totalCount);
}

Remarks

Async variant of ToActionResult<TValue>(Result<TValue>, ControllerBase, long, long, long). Useful for async paginated queries where range values are computed separately.

ToActionResultAsync<TValue>(ValueTask<Result<TValue>>, ControllerBase)

Converts a ValueTask-wrapped Result<TValue> to an ActionResult<TValue> with appropriate HTTP status code.

public static ValueTask<ActionResult<TValue>> ToActionResultAsync<TValue>(this ValueTask<Result<TValue>> resultTask, ControllerBase controllerBase)

Parameters

resultTask ValueTask<Result<TValue>>

The ValueTask containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

Returns

ValueTask<ActionResult<TValue>>

A ValueTask that represents the asynchronous operation, containing:

  • 200 OK with value if result is successful (except for Unit)
  • 204 No Content if result is successful and TValue is Unit
  • Appropriate error status code based on error type if result is failure

Type Parameters

TValue

The type of the value contained in the result.

Examples

[HttpGet("{id}")]
public ValueTask<ActionResult<UserDto>> GetUserAsync(Guid id) =>
    UserId.TryCreate(id)
        .BindAsync(_cacheService.GetUserAsync) // Returns ValueTask
        .MapAsync(user => new UserDto(user))
        .ToActionResultAsync(this);

Remarks

This overload is optimized for scenarios where the async operation frequently completes synchronously (e.g., cached results, in-memory operations). ValueTask can reduce allocations in these cases.

Use this when your service methods return ValueTask for performance optimization.

ToActionResultAsync<TValue>(ValueTask<Result<TValue>>, ControllerBase, long, long, long)

Converts a ValueTask-wrapped Result<TValue> to an ActionResult<TValue> with support for partial content responses using explicit range values (ValueTask variant).

public static ValueTask<ActionResult<TValue>> ToActionResultAsync<TValue>(this ValueTask<Result<TValue>> resultTask, ControllerBase controllerBase, long from, long to, long totalLength)

Parameters

resultTask ValueTask<Result<TValue>>

The ValueTask containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

from long

The starting index of the range (inclusive, 0-based).

to long

The ending index of the range (inclusive, 0-based).

totalLength long

The total number of items available.

Returns

ValueTask<ActionResult<TValue>>

A ValueTask that represents the asynchronous operation, containing:

  • 206 Partial Content with Content-Range header if the range is a subset
  • 200 OK if the range represents the complete set
  • Appropriate error status code if result is failure

Type Parameters

TValue

The type of the value contained in the result.

Remarks

ValueTask variant optimized for cached or frequently synchronous pagination scenarios.

ToActionResultAsync<TIn, TOut>(Task<Result<TIn>>, ControllerBase, Func<TIn, ContentRangeHeaderValue>, Func<TIn, TOut>)

Converts a Task-wrapped Result<TValue> to an ActionResult<TValue> with support for partial content responses (Task variant).

public static Task<ActionResult<TOut>> ToActionResultAsync<TIn, TOut>(this Task<Result<TIn>> resultTask, ControllerBase controllerBase, Func<TIn, ContentRangeHeaderValue> funcRange, Func<TIn, TOut> funcValue)

Parameters

resultTask Task<Result<TIn>>

The task containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

funcRange Func<TIn, ContentRangeHeaderValue>

Function that extracts ContentRangeHeaderValue from the input value.

funcValue Func<TIn, TOut>

Function that transforms the input value to the output type.

Returns

Task<ActionResult<TOut>>

A task that represents the asynchronous operation, containing:

  • 206 Partial Content with Content-Range header if the range is a subset
  • 200 OK if the range represents the complete set
  • Appropriate error status code if result is failure

Type Parameters

TIn

The type of the value contained in the input result.

TOut

The type of the value in the output ActionResult.

Examples

Async paginated endpoint:

[HttpGet]
public Task<ActionResult<IEnumerable<UserDto>>> GetUsersAsync(
    [FromQuery] int page = 0,
    [FromQuery] int pageSize = 25) =>
    _userService
        .GetPagedUsersAsync(page, pageSize)
        .ToActionResultAsync(
            this,
            funcRange: result => new ContentRangeHeaderValue(
                result.From, result.To, result.TotalCount),
            funcValue: result => result.Items.Select(u => new UserDto(u))
        );

// Returns 206 Partial Content with range headers for partial pages
// Returns 200 OK when all items fit in response

Remarks

ToActionResultAsync<TIn, TOut>(ValueTask<Result<TIn>>, ControllerBase, Func<TIn, ContentRangeHeaderValue>, Func<TIn, TOut>)

Converts a ValueTask-wrapped Result<TValue> to an ActionResult<TValue> with support for partial content responses (ValueTask variant).

public static ValueTask<ActionResult<TOut>> ToActionResultAsync<TIn, TOut>(this ValueTask<Result<TIn>> resultTask, ControllerBase controllerBase, Func<TIn, ContentRangeHeaderValue> funcRange, Func<TIn, TOut> funcValue)

Parameters

resultTask ValueTask<Result<TIn>>

The ValueTask containing the result object to convert.

controllerBase ControllerBase

The controller context used to create the ActionResult.

funcRange Func<TIn, ContentRangeHeaderValue>

Function that extracts ContentRangeHeaderValue from the input value.

funcValue Func<TIn, TOut>

Function that transforms the input value to the output type.

Returns

ValueTask<ActionResult<TOut>>

A ValueTask that represents the asynchronous operation, containing:

  • 206 Partial Content with Content-Range header if the range is a subset
  • 200 OK if the range represents the complete set
  • Appropriate error status code if result is failure

Type Parameters

TIn

The type of the value contained in the input result.

TOut

The type of the value in the output ActionResult.

Remarks

ValueTask variant optimized for scenarios with cached or frequently synchronous results.