Skip to content

Commit 3b86f05

Browse files
committed
Tmp
1 parent 2b174b7 commit 3b86f05

File tree

9 files changed

+146
-5
lines changed

9 files changed

+146
-5
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace BlazorUnitedApp.Client.Data;
5+
6+
public class ClientWeatherForecast
7+
{
8+
public DateOnly Date { get; set; }
9+
10+
public int TemperatureC { get; set; }
11+
12+
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
13+
14+
public string? Summary { get; set; }
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace BlazorUnitedApp.Client.Data;
5+
6+
public class ClientWeatherForecastService
7+
{
8+
private static readonly string[] Summaries = new[]
9+
{
10+
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
11+
};
12+
13+
public async Task<ClientWeatherForecast[]> GetForecastAsync(DateOnly startDate)
14+
{
15+
await Task.Yield();
16+
return await Task.FromResult(Enumerable.Range(1, 5).Select(index => new ClientWeatherForecast
17+
{
18+
Date = startDate.AddDays(index),
19+
TemperatureC = Random.Shared.Next(-20, 55),
20+
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
21+
}).ToArray());
22+
}
23+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
@page "/clientfetchdata/"
2+
@using BlazorUnitedApp.Client.Data
3+
@using Microsoft.AspNetCore.Components.Web
4+
@inject ClientWeatherForecastService ForecastService
5+
@inject NavigationManager NavigationManager
6+
@rendermode Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveWebAssembly
7+
8+
<PageTitle>Weather forecast</PageTitle>
9+
10+
<h1>Weather forecast</h1>
11+
12+
<p>This component demonstrates fetching data from a service.</p>
13+
14+
@if (Forecasts == null)
15+
{
16+
<p><em>Loading...</em></p>
17+
}
18+
else
19+
{
20+
<table class="table">
21+
<thead>
22+
<tr>
23+
<th>Date</th>
24+
<th>Temp. (C)</th>
25+
<th>Temp. (F)</th>
26+
<th>Summary</th>
27+
</tr>
28+
</thead>
29+
<tbody>
30+
@foreach (var forecast in Forecasts)
31+
{
32+
<tr>
33+
<td>@forecast.Date.ToShortDateString()</td>
34+
<td>@forecast.TemperatureC</td>
35+
<td>@forecast.TemperatureF</td>
36+
<td>@forecast.Summary</td>
37+
</tr>
38+
}
39+
</tbody>
40+
</table>
41+
}
42+
43+
<p>Current Url = @Page</p>
44+
45+
<ul>
46+
<li>
47+
<a href="clientfetchdata/?page=0">Page 0</a>
48+
</li>
49+
<li>
50+
<a href="clientfetchdata/?page=1">Page 1</a>
51+
</li>
52+
<li>
53+
<a href="clientfetchdata/?page=2">Page 2</a>
54+
</li>
55+
</ul>
56+
57+
@code {
58+
[PersistentState]
59+
[UpdateStateOnEnhancedNavigation(true)]
60+
public ClientWeatherForecast[]? Forecasts { get; set; }
61+
62+
public string Page { get; set; } = "";
63+
64+
protected override async Task OnInitializedAsync()
65+
{
66+
// Extract the page from the query string
67+
var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
68+
var pageParam = uri.Query.Split('&')
69+
.Select(q => q.Split('='))
70+
.FirstOrDefault(q => q.Length == 2 && q[0] == "page")?[1];
71+
int pageIndex = 1 + (int.TryParse(pageParam, out int parsedPage) ? parsedPage : 0);
72+
pageIndex *= 7;
73+
74+
Forecasts ??= await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now).AddDays(pageIndex));
75+
}
76+
77+
protected override void OnParametersSet()
78+
{
79+
Page = NavigationManager.Uri;
80+
}
81+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using BlazorUnitedApp.Client.Data;
5+
using BlazorUnitedApp.Client.Pages;
46
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
57

68
var builder = WebAssemblyHostBuilder.CreateDefault(args);
79

10+
builder.Services.AddSingleton<ClientWeatherForecastService>();
11+
812
await builder.Build().RunAsync();

src/Components/Samples/BlazorUnitedApp/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using BlazorUnitedApp;
5+
using BlazorUnitedApp.Client.Data;
56
using BlazorUnitedApp.Data;
67

78
var builder = WebApplication.CreateBuilder(args);
@@ -12,6 +13,7 @@
1213
.AddInteractiveServerComponents();
1314

1415
builder.Services.AddSingleton<WeatherForecastService>();
16+
builder.Services.AddSingleton<ClientWeatherForecastService>();
1517

1618
var app = builder.Build();
1719

@@ -30,6 +32,7 @@
3032

3133
app.MapStaticAssets();
3234
app.MapRazorComponents<App>()
35+
.AddAdditionalAssemblies(typeof(BlazorUnitedApp.Client.Pages.ClientFetchData).Assembly)
3336
.AddInteractiveServerRenderMode()
3437
.AddInteractiveWebAssemblyRenderMode();
3538

src/Components/Samples/BlazorUnitedApp/Routes.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Router AppAssembly="@typeof(App).Assembly">
1+
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="[typeof(BlazorUnitedApp.Client.Pages.ClientFetchData).Assembly]">
22
<Found Context="routeData">
33
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
44
<FocusOnNavigate RouteData="@routeData" Selector="h1" />

src/Components/Samples/BlazorUnitedApp/Shared/NavMenu.razor

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
<span class="bi bi-list-nested" aria-hidden="true"></span> Web assembly
3030
</NavLink>
3131
</div>
32+
<div class="nav-item px-3">
33+
<NavLink class="nav-link" href="clientfetchdata">
34+
<span class="bi bi-list-nested" aria-hidden="true"></span> Client Fetch Data
35+
</NavLink>
36+
</div>
3237
</nav>
3338
</div>
3439

src/Components/WebAssembly/WebAssembly/src/Rendering/WebAssemblyRenderer.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics;
45
using System.Diagnostics.CodeAnalysis;
56
using System.Runtime.CompilerServices;
67
using System.Runtime.InteropServices.JavaScript;
8+
using Microsoft.AspNetCore.Components.Infrastructure;
79
using Microsoft.AspNetCore.Components.Rendering;
810
using Microsoft.AspNetCore.Components.RenderTree;
911
using Microsoft.AspNetCore.Components.Web;
@@ -26,13 +28,15 @@ internal sealed partial class WebAssemblyRenderer : WebRenderer
2628
private readonly Dispatcher _dispatcher;
2729
private readonly ResourceAssetCollection _resourceCollection;
2830
private readonly IInternalJSImportMethods _jsMethods;
31+
private readonly ComponentStatePersistenceManager _componentStatePersistenceManager;
2932
private static readonly RendererInfo _componentPlatform = new("WebAssembly", isInteractive: true);
3033

3134
public WebAssemblyRenderer(IServiceProvider serviceProvider, ResourceAssetCollection resourceCollection, ILoggerFactory loggerFactory, JSComponentInterop jsComponentInterop)
3235
: base(serviceProvider, loggerFactory, DefaultWebAssemblyJSRuntime.Instance.ReadJsonSerializerOptions(), jsComponentInterop)
3336
{
3437
_logger = loggerFactory.CreateLogger<WebAssemblyRenderer>();
3538
_jsMethods = serviceProvider.GetRequiredService<IInternalJSImportMethods>();
39+
_componentStatePersistenceManager = serviceProvider.GetRequiredService<ComponentStatePersistenceManager>();
3640

3741
// if SynchronizationContext.Current is null, it means we are on the single-threaded runtime
3842
_dispatcher = WebAssemblyDispatcher._mainSynchronizationContext == null
@@ -46,9 +50,13 @@ public WebAssemblyRenderer(IServiceProvider serviceProvider, ResourceAssetCollec
4650
}
4751

4852
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "These are root components which belong to the user and are in assemblies that don't get trimmed.")]
49-
private void OnUpdateRootComponents(RootComponentOperationBatch batch)
53+
private void OnUpdateRootComponents(RootComponentOperationBatch batch, string appState)
5054
{
5155
var webRootComponentManager = GetOrCreateWebRootComponentManager();
56+
57+
var store = new PrerenderComponentApplicationStore(appState);
58+
_ = _componentStatePersistenceManager.RestoreStateAsync(store, WebPersistenceScenario.EnhancedNavigation);
59+
5260
for (var i = 0; i < batch.Operations.Length; i++)
5361
{
5462
var operation = batch.Operations[i];
@@ -74,6 +82,8 @@ private void OnUpdateRootComponents(RootComponentOperationBatch batch)
7482
}
7583
}
7684

85+
store.ExistingState.Clear();
86+
7787
NotifyEndUpdateRootComponents(batch.BatchId);
7888
}
7989

src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal sealed partial class DefaultWebAssemblyJSRuntime : WebAssemblyJSRuntime
2424

2525
public ElementReferenceContext ElementReferenceContext { get; }
2626

27-
public event Action<RootComponentOperationBatch>? OnUpdateRootComponents;
27+
public event Action<RootComponentOperationBatch, string>? OnUpdateRootComponents;
2828

2929
[DynamicDependency(nameof(InvokeDotNet))]
3030
[DynamicDependency(nameof(EndInvokeJS))]
@@ -94,12 +94,12 @@ public static void BeginInvokeDotNet(string? callId, string assemblyNameOrDotNet
9494

9595
[SupportedOSPlatform("browser")]
9696
[JSExport]
97-
public static void UpdateRootComponentsCore(string operationsJson)
97+
public static void UpdateRootComponentsCore(string operationsJson, string appState)
9898
{
9999
try
100100
{
101101
var operations = DeserializeOperations(operationsJson);
102-
Instance.OnUpdateRootComponents?.Invoke(operations);
102+
Instance.OnUpdateRootComponents?.Invoke(operations, appState);
103103
}
104104
catch (Exception ex)
105105
{

0 commit comments

Comments
 (0)