Soenneker.Blazor.Utils.JsObjects
4.0.83
Prefix Reserved
dotnet add package Soenneker.Blazor.Utils.JsObjects --version 4.0.83
NuGet\Install-Package Soenneker.Blazor.Utils.JsObjects -Version 4.0.83
<PackageReference Include="Soenneker.Blazor.Utils.JsObjects" Version="4.0.83" />
<PackageVersion Include="Soenneker.Blazor.Utils.JsObjects" Version="4.0.83" />
<PackageReference Include="Soenneker.Blazor.Utils.JsObjects" />
paket add Soenneker.Blazor.Utils.JsObjects --version 4.0.83
#r "nuget: Soenneker.Blazor.Utils.JsObjects, 4.0.83"
#:package Soenneker.Blazor.Utils.JsObjects@4.0.83
#addin nuget:?package=Soenneker.Blazor.Utils.JsObjects&version=4.0.83
#tool nuget:?package=Soenneker.Blazor.Utils.JsObjects&version=4.0.83
Soenneker.Blazor.Utils.JsObjects
A scoped registry for creating, caching, and disposing stateful JavaScript object references returned by ES module exports.
Use it when an exported factory creates a JavaScript object whose state should be reused across multiple Blazor interop calls. Stateless module functions do not need this registry.
Installation
dotnet add package Soenneker.Blazor.Utils.JsObjects
using Soenneker.Blazor.Utils.JsObjects.Registrars;
builder.Services.AddJsObjectRegistryAsScoped();
Inject IJsObjectRegistry into the component or service that wraps the JavaScript API.
JavaScript factory
The export must take no arguments and return an object. The object’s functions become methods on the resulting IJSObjectReference:
export function createCounter() {
let value = 0;
return {
increment(step = 1) {
value += step;
return value;
},
reset() {
value = 0;
}
};
}
Place the module in the application’s static web assets, for example wwwroot/js/counter.js.
Wrap the object in a typed service
using Microsoft.JSInterop;
using Soenneker.Blazor.Utils.JsObjects.Abstract;
public sealed class CounterClient(IJsObjectRegistry objects)
{
private const string ModulePath = "/js/counter.js";
private const string Factory = "createCounter";
public async ValueTask<int> Increment(
int step,
CancellationToken cancellationToken = default)
{
IJSObjectReference counter =
await objects.Get(ModulePath, Factory, cancellationToken);
return await counter.InvokeAsync<int>(
"increment",
cancellationToken,
step);
}
}
Call browser interop after interactive rendering. The same registry scope returns the same object reference for repeated calls with the same exact module path and export name. Different spellings, relative paths, query strings, or export names form different cache entries.
The registry owns returned references. Do not dispose them directly; remove them through the registry so its cache cannot return a disposed handle.
Reset cached state
Remove one factory result when that object’s JavaScript state is no longer valid:
bool removed = await objects.RemoveObject(
"/js/counter.js",
"createCounter");
The next Get for that pair calls the factory again.
Remove every cached object created from a module while leaving the imported module available:
await objects.RemoveObjectsForModule("/js/counter.js", cancellationToken);
Or remove the objects and evict the imported module:
bool anythingRemoved = await objects.RemoveModuleAndObjects(
"/js/counter.js",
cancellationToken);
The last method returns true when at least one object or the module cache entry was removed. Use module-wide removal only when this registry is the exclusive owner of that module cache entry; disposing a shared imported module can invalidate other consumers.
Creation and removal operations are serialized within the registry so a module eviction cannot race a new cached object creation. Do not invoke a previously returned reference after removing it.
Lifetime and failures
In Blazor Server, scoped state normally lasts for the circuit. In WebAssembly, a scoped service normally lasts for the application. Remove short-lived objects when their owning widget is destroyed; remaining cached references are disposed with the registry scope.
A cancellation token cancels waiting for creation or removal, but it cannot undo JavaScript work that already completed. Factory import errors, missing exports, non-object return values, and JavaScript exceptions propagate to the caller.
Keep module paths and export names as trusted application constants. Dynamic module import executes code in the page, so never derive either value directly from user input. Returned values and callbacks that originate in JavaScript remain untrusted data and require normal validation.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Soenneker.Asyncs.Locks (>= 4.0.86)
- Soenneker.Blazor.Utils.ModuleImport (>= 4.0.1894)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.83 | 0 | 9/15/2026 |
| 4.0.82 | 42 | 9/14/2026 |
| 4.0.81 | 51 | 9/13/2026 |
| 4.0.80 | 49 | 9/12/2026 |
| 4.0.78 | 47 | 9/12/2026 |
| 4.0.77 | 60 | 9/12/2026 |
| 4.0.75 | 73 | 9/9/2026 |
| 4.0.74 | 87 | 9/8/2026 |
| 4.0.73 | 93 | 9/8/2026 |
| 4.0.72 | 92 | 9/7/2026 |
| 4.0.71 | 86 | 9/7/2026 |
| 4.0.70 | 95 | 9/7/2026 |
| 4.0.69 | 89 | 9/5/2026 |
| 4.0.68 | 93 | 9/4/2026 |
| 4.0.67 | 92 | 9/4/2026 |
| 4.0.66 | 89 | 9/4/2026 |
| 4.0.65 | 87 | 9/4/2026 |
| 4.0.64 | 91 | 9/3/2026 |
| 4.0.63 | 82 | 9/1/2026 |
| 4.0.62 | 85 | 8/31/2026 |