loading
Note:
What crosses the boundary, and what doesn't Every value going to or from JavaScript is marshalled as JSON, so what the browser clones is the marshalled shape. Within plain data the round trip is faithful; a DateTime arrives as a string and comes back a string, and the Map, Set and ArrayBuffer types structured clone preserves have no representation here to preserve. This is a deep copy and a compatibility check - not a way to smuggle types past the boundary.

Support check

IsSupported

Returns true when the runtime exposes structuredClone. During prerender/SSR the check returns false rather than throwing, so defer it to OnAfterRenderAsync.

C#
@inject Bit.Butil.StructuredClone structuredClone

var supported = await structuredClone.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Deep-copy a graph

Clone

A deep copy with no ICloneable to implement and no copy constructor to keep in sync: the value goes out, a detached copy comes back. Mutating the copy here leaves the original untouched, nested objects and all.

C#
var copy = await structuredClone.Clone(order);

copy!.Lines[0].Quantity = 99;   // the original is unaffected
Live sample
clone output
Results will appear here when you interact with the samples.

Will the browser take this?

CanClone

The same algorithm decides what postMessage, IndexedDB and history.pushState accept - so this answers 'will this payload survive' before you find out from a DataCloneError at the far end. Worth calling once against a representative payload rather than per message.

C#
if (await structuredClone.CanClone(payload) is false)
{
    // don't hand it to BroadcastChannel / IndexedDb / History
}
Live sample
check output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes structuredClone. Returns default (false) during prerender/SSR instead of throwing.
Clone
ValueTask<T?> Clone<T>(T value)
Deep-copies a value through the browser's structured clone algorithm. Default when the runtime has no structuredClone or the value isn't cloneable.
CanClone
ValueTask<bool> CanClone<T>(T value)
Whether the structured clone algorithm accepts this value - the same test postMessage, IndexedDB and history.pushState apply.
An unhandled error has occurred. Reload 🗙