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; } } }}

