user8207463
user8207463

Reputation:

IAsyncEnumerable view component return in asp.net core

I have this project that is working fine:

service class:

 public async Task<IAsyncEnumerable<ContratoDTO>> ContratoServiceGetAll()
    {
        List<ContratoDTO> listaDeContrato = new List<ContratoDTO>();
        listaDeContrato = await ContratoRepository.GetAllAsync().Result.Select(u => new ContratoDTO(u)).ToList();
        return listaDeContrato.ToAsyncEnumerable();
    }

ViewComponent Class:

public async Task<IViewComponentResult> InvokeAsync()
    {
        ContratoViewModel listaContrato = new ContratoViewModel
        {
            Contratos = await ContratoSerivce.ContratoServiceGetAll()
        };
         return View(listaContrato);
    }

and my component on the Shared View folder:

   <tbody>
        @if (Model.Contratos != null)
        {
            @foreach (var item in Model.Contratos.ToEnumerable())
            {

                <tr>
                    <th scope="row">@item.NuContrato</th>
                    <td>@item.VlContrato</td>
                    <td>36</td>
                    <td>@item.DtEmissao</td>
                    <td>@item.DtRetorno</td>
                    <td>Rio de Janeiro</td>
                </tr>
            }
        }
    </tbody>

It works but the Model.Contratos.ToEnumerable() is this the best approach ? If i take the ToEnumerable() method out it will throw an error:

'Error CS0202: foreach requires that the return type 'IAsyncEnumerator<ContratoDTO>' of 'IAsyncEnumerable<ContratoDTO>.GetEnumerator()' must have a suitable public MoveNext method and public'

ps: The ContratoViewModel has a property of IAsyncEnumerable generic type of T my DTO.

Upvotes: 0

Views: 1173

Answers (1)

Sour
Sour

Reputation: 1

For all the years that I've been using Stack Overflow, this is my first time responding to anyone as I think it's time I should contribute to the community. I hope this is helpful.

IAsyncEnumerable<T> can be awaited on similarly like Task<T>. It doesn't need to be wrapped. A comment to your question shows that you may lose the benefit of IAsyncEnumerable<T> if you use .Result.Select(u => new ContratoDTU(u)).ToList();. I agree as .ToList() is synchronous and will block until it's completed.

While using the variables in your service class, the following is a shorthanded revision:

public async IAsyncEnumerable<ContratoDTO> ContratoServiceGetAll()
{
    foreach (var u in await ContratoRepository.GetAllAsync())
        yield return new ContratoDTO(u);
}

Also, the .ToEnumerable() statement in your component (assuming you meant .AsEnumerable() from extension method Enumerable.AsEnumerable<TSource>(this IEnumerable<TSource> source)) will cause the view to block at that moment to execute the Model.Contractos query (again, assuming ContractoRepository.GetAllAsync() is returning a IQueryable<T>).

It's redundant to have .ToEnumerable() as the the iteration will begin once @foreach (var item in Model.Contractos) is evaluated.

Upvotes: 0

Related Questions