I want to build a website using MudBlazor and C# on .NET 9. On one of the pages, I want to display images, which are loaded in the OnInitializedAsync event handler. To handle the case when the user leaves the page, I have implemented a Dispose method.
However, I noticed that both OnInitializedAsync and Dispose are executed twice.
Log output:
OnInitializedAsync executed.
Dispose executed.
OnInitializedAsync executed.
Dispose executed.
This behavior only occurs when images are displayed.
I am wondering why this happens and how I can prevent unnecessary disk (or later database) access.
I have already tried using a _isInitialized flag set to true to prevent a second disposal, but Dispose is still called twice.
I also attempted using OnAfterRenderAsync with _isRendered flag, but since OnAfterRenderAsync gets triggered multiple times, it is not suitable because the images are reloaded too often.
I came across this thread. I wanted to implement the answers contained there, but the thread is about Blazor in general, and it's from 2019. I don't have the _Host.cshtml in the project (so, my question is not a duplicate).
I then tried the other answer, using
@rendermode @(new InteractiveServerRenderMode(prerender:false))
This has the effect that the second dispose is no longer called when rendering, otherwise only when you leave the page. Nevertheless, the data is fetched twice.
I use a server-side application. The template when creating the project is this one:
MudBlazor was installed as a Nuget package from the beginning.
I have provided a minimal, runnable example for you to check.
@page "/"
@using MudBlazor
@implements IDisposable
@inject NavigationManager Navigation
<MudLayout>
@if (Foos.Count > 0)
{
<MudGrid Class="mt-4" Spacing="0">
@foreach (Foo f in Foos)
{
@if (f.ImageAsByteArray != null)
{
<MudItem xs="12" sm="6" md="4">
<MudCardContent Dense="true">
<MudImage Src="@($"data:image;base64,{Convert.ToBase64String(f.ImageAsByteArray)}")" Elevation="25" Class="rounded-lg ma-2 d-block mx-auto" Width="350" Height="350" />
</MudCardContent>
</MudItem>
}
}
</MudGrid>
}
</MudLayout>
@code {
private List<Foo> Foos = new List<Foo>();
protected override async Task OnInitializedAsync()
{
Foos = await LoadImages();
Console.WriteLine("OnInitializedAsync executed.");
}
public void Dispose()
{
Console.WriteLine("Dispose executed.");
foreach (Foo foo in Foos)
{
foo.CleanUp();
}
}
private Task<List<Foo>> LoadImages()
{
List<Foo> foos = new List<Foo>();
Foo foo1 = new Foo(System.IO.File.ReadAllBytes(@$"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\Pictures\20190119_131055 2.jpg"));
foos.Add(foo1);
Foo foo2 = new Foo(System.IO.File.ReadAllBytes(@$"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\Pictures\20210117_010401.jpg"));
foos.Add(foo2);
return Task.FromResult(foos);
}
}
namespace BlazorMinimalExample2
{
public class Foo
{
public byte[]? ImageAsByteArray { get; set; }
public Foo(byte[] stuff)
{
this.ImageAsByteArray = stuff;
}
public void CleanUp()
{
if (this.ImageAsByteArray != null)
{
this.ImageAsByteArray = null;
}
}
}
}

