Skip to content

Commit 76e4d18

Browse files
authored
Update ResourceCollectionProvider to take advantage of Declarative persistent component state (#61748)
* Refactoring + registrations. * Allow multiple instances of `IPersistentServiceRegistration`. * Skip assembly name in for all internal types.
1 parent caf0f3f commit 76e4d18

File tree

6 files changed

+35
-28
lines changed

6 files changed

+35
-28
lines changed

src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,16 @@ private static string ComputeKey(Type keyType, string propertyName)
211211
// This happens once per type and property combo, so allocations are ok.
212212
var assemblyName = keyType.Assembly.FullName;
213213
var typeName = keyType.FullName;
214-
var input = Encoding.UTF8.GetBytes(string.Join(".", assemblyName, typeName, propertyName));
215-
return Convert.ToBase64String(SHA256.HashData(input));
214+
215+
// Internal classes can be bundled in different assemblies during prerendering and WASM rendering.
216+
bool isTypeInternal = (!keyType.IsPublic && !keyType.IsNested) || keyType.IsNestedAssembly;
217+
var inputString = isTypeInternal
218+
? string.Join(".", typeName, propertyName)
219+
: string.Join(".", assemblyName, typeName, propertyName);
220+
221+
var input = Encoding.UTF8.GetBytes(inputString);
222+
var hash = SHA256.HashData(input);
223+
return Convert.ToBase64String(hash);
216224
}
217225

218226
internal static IEnumerable<PropertyInfo> GetCandidateBindableProperties(

src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public static IRazorComponentsBuilder AddRazorComponents(this IServiceCollection
7575
services.TryAddScoped<WebAssemblySettingsEmitter>();
7676

7777
services.TryAddScoped<ResourceCollectionProvider>();
78+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<ResourceCollectionProvider>(services, RenderMode.InteractiveWebAssembly);
7879

7980
ComponentsMetricsServiceCollectionExtensions.AddComponentsMetrics(services);
8081
ComponentsMetricsServiceCollectionExtensions.AddComponentsTracing(services);

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ private static void InitializeResourceCollection(HttpContext httpContext)
149149
var resourceCollectionProvider = resourceCollectionUrl != null ? httpContext.RequestServices.GetService<ResourceCollectionProvider>() : null;
150150
if (resourceCollectionUrl != null && resourceCollectionProvider != null)
151151
{
152-
resourceCollectionProvider.SetResourceCollectionUrl(resourceCollectionUrl.Url);
152+
resourceCollectionProvider.ResourceCollectionUrl = resourceCollectionUrl.Url;
153153
resourceCollectionProvider.SetResourceCollection(resourceCollection ?? ResourceAssetCollection.Empty);
154154
}
155155
}

src/Components/Endpoints/test/RazorComponentsServiceCollectionExtensionsTest.cs

Lines changed: 7 additions & 1 deletion
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 Microsoft.AspNetCore.Components;
5+
using Microsoft.AspNetCore.Components.Forms;
56
using Microsoft.AspNetCore.Components.Forms.Mapping;
67
using Microsoft.AspNetCore.Components.Routing;
78
using Microsoft.AspNetCore.Hosting;
@@ -92,7 +93,12 @@ private Dictionary<Type, Type[]> MultiRegistrationServiceTypes
9293
{
9394
typeof(SupplyParameterFromFormValueProvider),
9495
typeof(SupplyParameterFromQueryValueProvider),
95-
}
96+
},
97+
[typeof(IPersistentServiceRegistration)] = new[]
98+
{
99+
typeof(ResourceCollectionProvider),
100+
typeof(AntiforgeryStateProvider),
101+
},
96102
};
97103
}
98104
}

src/Components/Shared/src/ResourceCollectionProvider.cs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,27 @@ namespace Microsoft.AspNetCore.Components;
1111

1212
internal class ResourceCollectionProvider
1313
{
14-
private const string ResourceCollectionUrlKey = "__ResourceCollectionUrl";
1514
private string? _url;
16-
private ResourceAssetCollection? _resourceCollection;
17-
private readonly PersistentComponentState _state;
18-
private readonly IJSRuntime _jsRuntime;
1915

20-
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Strings are not trimmed")]
21-
public ResourceCollectionProvider(PersistentComponentState state, IJSRuntime jsRuntime)
16+
[SupplyParameterFromPersistentComponentState]
17+
public string? ResourceCollectionUrl
2218
{
23-
_state = state;
24-
_jsRuntime = jsRuntime;
25-
_ = _state.TryTakeFromJson(ResourceCollectionUrlKey, out _url);
19+
get => _url;
20+
set
21+
{
22+
if (_url != null)
23+
{
24+
throw new InvalidOperationException("The resource collection URL has already been set.");
25+
}
26+
_url = value;
27+
}
2628
}
2729

28-
[MemberNotNull(nameof(_url))]
29-
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Strings are not trimmed")]
30-
internal void SetResourceCollectionUrl(string url)
30+
private ResourceAssetCollection? _resourceCollection;
31+
private readonly IJSRuntime _jsRuntime;
32+
public ResourceCollectionProvider(IJSRuntime jsRuntime)
3133
{
32-
if (_url != null)
33-
{
34-
throw new InvalidOperationException("The resource collection URL has already been set.");
35-
}
36-
_url = url;
37-
PersistingComponentStateSubscription registration = default;
38-
registration = _state.RegisterOnPersisting(() =>
39-
{
40-
_state.PersistAsJson(ResourceCollectionUrlKey, _url);
41-
registration.Dispose();
42-
return Task.CompletedTask;
43-
}, RenderMode.InteractiveWebAssembly);
34+
_jsRuntime = jsRuntime;
4435
}
4536

4637
internal async Task<ResourceAssetCollection> GetResourceCollection()

src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ internal void InitializeDefaultServices()
308308
Services.AddSupplyValueFromPersistentComponentStateProvider();
309309
Services.AddSingleton<IErrorBoundaryLogger, WebAssemblyErrorBoundaryLogger>();
310310
Services.AddSingleton<ResourceCollectionProvider>();
311+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<ResourceCollectionProvider>(Services, RenderMode.InteractiveWebAssembly);
311312
Services.AddLogging(builder =>
312313
{
313314
builder.AddProvider(new WebAssemblyConsoleLoggerProvider(DefaultWebAssemblyJSRuntime.Instance));

0 commit comments

Comments
 (0)