After much effort I finally tracked down the root cause of what I was experiencing. Whenever the RouteData is injected as a CascadingParameter into a Layout and then you navigate to a different Layout, Blazor will construct two new components and initialize them both before disposing of one of them. So any data fetched during OnInitializedAsync will be performed twice without any way of detecting it.
Does anyone have a workaround for this? I found this old ticket on their repo but looks like there isn't much activity. https://github.com/dotnet/aspnetcore/issues/20637
App.razor:
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<CascadingValue Value="@routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</CascadingValue>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
MyLayout.razor:
@inherits LayoutComponentBase
@layout MainLayout
<a href="/someOtherPageWithoutThisLayout">Go Back</a>
@Body
@code {
[CascadingParameter] RouteData RouteData { get; set; }
}
The lifecycle of the destination component will look something like the following:
MyComponent constructed: HashCode=216708300
MyComponent OnInitializedAsync: HashCode=216708300
MyComponent constructed: HashCode=785069820
MyComponent OnInitializedAsync: HashCode=785069820
MyComponent disposing: HashCode=216708300