I have a controller method of this signature:
public async IAsyncEnumerable<MyDto> Get()
It works fine but I need to do some request validation and return 401, 400, and other codes accordingly, which it does not support. Alternatively, the following signature does not compile:
public async Task<ActionResult<IAsyncEnumerable<MyDto>>> Get()
Error:
Cannot implicitly convert type 'Microsoft.AspNetCore.Mvc.UnauthorizedResult' to 'MyApi.Responses.MyDto'
The full method:
public async IAsyncEnumerable<MyDto> Get()
{
if (IsRequestInvalid())
{
// Can't do the following. Does not compile.
yield return Unauthorized();
}
var retrievedDtos = _someService.GetAllDtosAsync(_userId);
await foreach (var currentDto in retrievedDtos)
{
yield return currentDto;
}
}
Any ideas? Can't seem to believe that Microsoft has designed IAsyncEnumerable
to be used without the possibility/flexibility of returning anything else.
IAsyncEnumerable
. If you usedasync Task<MyDTO>
you'd have the same problem. If you want to return specific responses, returnIActionResult
orActionResult<T>
– BungIn such a case, it's common to mix an ActionResult return type with the primitive or complex return type. Either IActionResult or ActionResult<T> are necessary to accommodate this type of action.
– BungTask<ActionResult<MyDto>>
whereas I cannot doTask<ActionResult<IAsyncEnumerable<MyDto>>>
(as mentioned in the question). And I need IAsyncEnumerable to pass the results to the serializer as they arrive. – RoswellActionResult
orIActionResult
, you can't return a status. The question is how to return that, and keep the benefits of IAsyncEnumerable. Looking at the source for ObjectResultExecutor, the class that actually sends object results, I see it has code to handle IAsyncEnumerable – BungActionResult<IAsyncEnumerable>
, eg:return Ok(retrievedDtos)
. – Bung