Как установить код состояния 404 при возврате пустого IAsyncEnumerable <T> в ASP.NET Core (.NET 6)
У меня есть действие контроллера, которое возвращает IAsyncEnumerable. Он запрашивает источник данных, и, если данные доступны, каждый результат представляет собой «yield return» -ed (сериализуется с помощью System.Text.Json и возвращается клиенту). Но как я могу установить код состояния на 404, если результатов нет? Прямо сейчас, если результатов нет, метод возвращает пустой массив JSON с кодом состояния = 200.
public async IAsyncEnumerable<string> GetStrings()
{
IEnumerable<string> stringResults = await myData.GetStringsAsync();
if (stringResults is object && stringResults.Any())
{
foreach (string result in stringResults)
{
yield return result;
}
}
else
{
return NotFound(); //CS1622: Cannot return a value from an iterator....
}
}
Обновлять
Я хочу, чтобы эта потоковая передача была предоставлена клиенту, как только будут получены результаты. Если я вернусь
1 ответ
Вы не можете смешивать асинхронный генератор и действие mvc, которое возвращает
NotFound()
. Но можно написать двумя способами.
public async Task<IActionResult> GetStrings()
{
IEnumerable<string> stringResults = await myData.GetStringsAsync();
if (stringResults == null)
return NotFound();
var e = stringResults.GetEnumerator();
if (!e.MoveNext())
return NotFound();
return Ok(AsEnum(e));
async IAsyncEnumerable<string> AsEnum(IEnumerator<string> e){
do {
yield return e.Current;
} while (e.MoveNext());
}
}
С любой дополнительной обработкой ошибок и удалением счетчика.
Однако здесь все же есть разница в поведении. В отличие от
async Task
метод
IEnumerable
& методы генератора не запускаются до первого вызова
.MoveNext[Async]
.
Поскольку ваша предыдущая реализация вернула бы
IAsyncEnumerable
в MVC перед выполнением любого вашего действия. Заголовки HTTP будут написаны, и сериализатор json вызовет
IAsyncEnumerable.MoveNextAsync
, перед твоим
GetStringAsync
сервис даже называется.
Если вы хотите дождаться первого результата, прежде чем возвращать 200/404, вам нужно дождаться, пока серверная служба что-то вернет, прежде чем вы сможете писать какие-либо заголовки HTTP.
Использование времени до первого байта в качестве метрики здесь полностью вводит в заблуждение.