Home > database >  Blazor WASM - @foreach cannot operate on variable Task<IEnumerable> because Task<IEnumerabl
Blazor WASM - @foreach cannot operate on variable Task<IEnumerable> because Task<IEnumerabl

Time:08-25

I'm using Blazor Web Assembly and i'm trying to display a Section Header with its Section Content.

 int sectionId;

@foreach (var item in Sections)
{
                //Display Section Name
    <h2>@item.SectionName</h2>

    //Get ID For Section Content
    sectionId = item.Id;

    @foreach (var content in GetContent(sectionId))
    {

    }

}

But i'm getting the following error on the GetContent(id) Method.

Error - @foreach cannot operate on variable Task because Task<IEnumerable> doesn't contain a public instance

In my component base class, the function is returning a IEnumerable collection of the DTO.

    public async Task<IEnumerable<ModuleContentDto>> GetContent(int sectionId)
    {
        
        var content = await ModuleService.GetContent(sectionId);

        return content;
    }       

Service Class

public async Task<IEnumerable<ModuleContentDto>> GetContent(int sectionId)
    {
        var response = await this.httpClient.GetAsync($"api/Module/{sectionId}/GetItems");

        try
        {
            if (response.IsSuccessStatusCode)
            {
                if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
                {
                    return Enumerable.Empty<ModuleContentDto>();
                }

                return await response.Content.ReadFromJsonAsync<IEnumerable<ModuleContentDto>>();
            }
            else
            {
                var message = await response.Content.ReadAsStringAsync();
                throw new Exception($"Http status code: {response.StatusCode} message: {message}");
            }
        }
        catch (Exception)
        {

            throw;
        }

but I cant iterate over the collection in my razor component? Please can someone suggest the best way to do it as iv tried converting to a LIST and a ENumerator.

Thanks, Tom

CodePudding user response:

Your immediate problem is that you do not await your task. That should be a simple fix.

However, you should really not mix Task and IEnumerable. Asyncronous execution and deferred execution in the same method is really a bug waiting to happen. If you want to execute this async then pick a materialized collection, like a List<> or simply an array as your return type.

CodePudding user response:

GetContent is async and returning a Task. However, you are calling it without await in your @foreach.

You need to call GetContent in the @code section of your razor page, for example in OnInitializedAsync() and store your IEnumerable<ModuleContentDto> in a variable. Then you can iterate with foreach.

@foreach (var item in Sections)
{
    //Display Section Name
    <h2>@item.SectionName</h2>

    //Get ID For Section Content
    @{
      int sectionId = item.Id;
    }

    @if(ModuleContentDtoDict.ContainsKey(sectionId))
    {
      @foreach (var content in ModuleContentDtoDict[sectionId])
      {

      }
    }

}

@code{
  public Dictionary<int, IEnumerable<ModuleContentDto>> ModuleContentDtoDict { get; set; } = new Dictionary<int, IEnumerable<ModuleContentDto>>();

  protected override async Task OnInitializedAsync()
  {
    foreach(var item in Sections)
    {
      int sectionId = item.Id;
      IEnumerable<ModuleContentDto> moduleContentDtoList = await GetContent(sectionId);
      ModuleContentDtoDict.Add(sectionId, moduleContentDtoList);
    }
  }
}
  • Related