dotnet / dotnet/aspnetcore

[Validation] C# unions across JavaScript interop

Open
#68,481 1 comment 0 reactions 1 assignee Claimed by @vendasankarsf3945 View on GitHub
area-blazor Validation validation-scenario
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

**Scenario contact:** @oroztocil

## Scenario

An app exchanges C# union values with JavaScript in both directions: as arguments to JavaScript calls, as values returned from JavaScript, and as parameters and return values of methods JavaScript calls back into .NET. This validates that a union serializes as its active case, comes back as the right case, and fails understandably when the incoming JSON matches no case.

## Minimum build

.NET 11 Preview 7 or later.

## Configurations to cover

* Blazor Web App
* [ ] Static SSR
* [x] Interactive Server
* [x] Interactive WebAssembly
* [ ] Interactive Auto
* [x] Standalone WebAssembly
* [ ] Hybrid (MAUI)

## Also exercise

* [x] Published output
* [ ] An existing .NET 10 app upgraded to .NET 11
* [x] Trimming or ahead-of-time compilation
* [ ] More than one server instance, or a proxy in front
* [ ] Hot Reload
* [ ] An IDE as well as the command line
* [ ] Container

## Setup

Union types are a preview language feature, so each project needs `preview`.

## What to build

An app with a small JavaScript module and a page that exercises interop in both directions. Define an unambiguous union such as `(int, string)`, a nullable union such as `(int?, string)`, and a union of two records whose JSON shapes are hard to tell apart. Pass each of them to JavaScript, return each of them from JavaScript, and add a method JavaScript can invoke that both accepts and returns a union. Show the results in the page, and watch what actually crosses the boundary in the browser console.

## Things to try

* A union whose active case is null.
* A union nested inside a larger object rather than passed on its own.
* JavaScript returning a shape that matches no declared case, or that matches more than one.
* The two-record union with and without a `[JsonUnion]` classifier.

## Expected behavior

Only the active case crosses the boundary, it comes back as the same case, and anything JavaScript sends that does not fit is reported rather than guessed at.

### Must hold

* An integer case arrives in JavaScript as a number, a string case as a string, and a record case as that record's own object, with no wrapper object around the active case.
* A value returned from JavaScript becomes the same case it was sent as, including when the active case is null.
* A union passed to and returned from a method JavaScript invokes on .NET round-trips as the same case.
* JSON matching no declared case produces an error naming the problem rather than a default value.
* The ambiguous record union either resolves through its classifier or fails with a message naming the ambiguity.

### Expected differences between configurations

No user-observable differences are expected between the covered configurations.

## Evidence to capture

The actual JSON that crossed the boundary for each union case, taken from the browser console or the network log, rather than a description of it.

## Documentation to use

* [C# union types, .NET 11 release notes](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-11#c-union-types)
* [Union types, C# language reference](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/union)
* [Call JavaScript from .NET](https://learn.microsoft.com/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-11.0)
* [Call .NET from JavaScript](https://learn.microsoft.com/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-11.0)

## What to report

Report results using the format described in the [validation testing manual](https://github.com/dotnet/aspnetcore/issues/68479). Include link to a repository with the test app.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.