async-awaitdependency-injectionblazormaui-blazor

How to async code Blazor Dependency Injection in components?


I'm starting to study MAUI Blazor to migrate some apps I have in Android an iOS. I'm struggling a bit with Dependency Injection with Blazor components.

Here is the Card I've created to list some items:

<h3>LoteCard</h3>

<div class="row">
    @foreach (Lote l in lstLotesFiltrada)
    {
        <div class="col-sm-4 p-2">
            <div class="lote-card">
                <div class="lote-card-header">
                    <h3>l.numLote:l.pesoLote</h3>
                </div>
                if (visible){
                    <p> this is visible</p>
                }
            </div>
        </div>
    }
</div>


@code {
    [Parameter]
    public bool visible { get; set; }

    [Parameter]
    public List<Lote> lstLotesFiltrada { get; set; } = new List<Lote>();

}

And here is the code for the CardComponent:


<LoteCard lstLotesFiltrada="lstLotesFiltrada" visible="isVisible"/>


@code {
    private bool isVisible = true;

    private List<Lote> lstLotesFiltrada = new List<Lote>();

    [Inject]
    private ILotesManager lotesManager { get; set; } = new LotesManager();

    protected override async void OnInitialized()
    {
        base.OnInitialized();

        loadLotes();

        int x = 1;

    }

    private async void loadLotes()
    {
        List<Lote> tmpLstLotesFiltrada = await lotesManager.getLoteByIdPropriedade(idPropriedade: "-Mfp3q1ma0ZkFsIUXqyE");

        lstLotesFiltrada = tmpLstLotesFiltrada;

    }

The problem is that when I call "loadLotes()" it awaits the result. But, the code moves on and the forLoop is executed at the Card with an empty list. Right after that the "getLote..." method returns the list with items.

The order of execution is:

  1. Fire loadLotes;
  2. "x=1"
  3. ForLoop at the Card
  4. "lstLotesFiltrada = tmpLstLotesFiltrada"

I understand this is related to the async code but am struggligng to see the solution.

Please help! Thanks!


Solution

  • Your async method should return a Task, and you should override the async OnInitializedAsync correctly.

    protected override async Task OnInitializedAsync()
    {
      await base.OnInitializedAsync();
    
      await loadLotes();
    
      int x = 1;
    }
    
    private async Task loadLotes()
    {
      List<Lote> tmpLstLotesFiltrada = await 
        lotesManager.getLoteByIdPropriedade(idPropriedade: "-Mfp3q1ma0ZkFsIUXqyE");
    
      lstLotesFiltrada = tmpLstLotesFiltrada;
    }
    

    As per the docs:

    For methods other than event handlers that don't return a value, you should return a Task instead, because an async method that returns void can't be awaited. Any caller of such a method must continue to completion without waiting for the called async method to finish.

    https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-return-types#void-return-type