Skip to content

[Prototype] Typed browser platform APIs for Blazor, starting with Web Storage - #69305

Draft
jsakamotoIGJP wants to merge 9 commits into
dotnet:mainfrom
jsakamotoIGJP:components-platform-prototype
Draft

jsakamotoIGJP wants to merge 9 commits into
dotnet:mainfrom
jsakamotoIGJP:components-platform-prototype

Conversation

@jsakamotoIGJP

Copy link
Copy Markdown
  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

A prototype of typed browser platform APIs for Blazor

Description

A draft for design feedback, not a request to merge. Milos asked me to open it here so that @maraf and @javiercn can review it. The API proposal is #69304.

This adds Microsoft.AspNetCore.Components.Platform, which gives typed access to standard browser APIs instead of string-based IJSRuntime calls. The first family is Web Storage. DOM APIs and application-specific JavaScript are out of scope.

  • IBrowserPlatform, Window, Storage, and AddBrowserPlatform.
  • LocalStorage and SessionStorage are extension properties on Window, so the trimmer can remove the one an application does not use.
  • ProtectedLocalStorage and ProtectedSessionStorage use the projection for their default registration. Their public constructors still work.
  • Unit tests, coverage for the new registrations in Microsoft.AspNetCore.Components.Server.Tests, and a test application with E2E tests for Interactive Server and WebAssembly.
  • .github/skills/port-components-platform-api/SKILL.md, which writes down the rules for adding the next family, including the trimming one.

The first two commits are by @kotlarmilos, from kotlarmilos#1 and kotlarmilos#2, rebased on the current main. Javier already reviewed the prototype and asked to remove the lock in Storage, which a later commit does.

Questions

  1. Shared framework, or a separate package? It is a separate package today, but Microsoft.AspNetCore.Components.Server is in the shared framework and references it.
  2. The E2E tests do not run in CI, and that is on purpose. I left PlatformTestApp.E2E.Tests out because this is a prototype.
  3. Extension properties cost discoverability. Without the namespace import, the editor does not suggest LocalStorage after you type Window.. Normal properties are easier to find, but then the trimmer cannot remove the unused one.
  4. The skill file states the design rules this prototype follows. Please review it alongside the code, or tell me to drop it if it doesn't belong in this PR.

kotlarmilos and others added 5 commits September 15, 2026 14:46
Introduce Microsoft.AspNetCore.Components.Platform with typed Web Storage, URL, and Fetch projections. Add focused unit and browser coverage through Microsoft.AspNetCore.Components.Testing and include a reusable porting skill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 72b07274-a61f-41d3-ac15-3d0df5c4f818
Remove the URL and Fetch projections and migrate protected browser storage registrations to the typed Web Storage API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 72b07274-a61f-41d3-ac15-3d0df5c4f818
The synchronization context guarantees that only one thread runs at a
time, so Storage does not need a lock.

Review comment.
kotlarmilos#1 (comment)
@github-actions github-actions Bot added area-blazor Includes: Blazor, Razor Components area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework labels Sep 15, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey @dotnet/aspnet-build, looks like this PR is something you want to take a look at.

@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Sep 15, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Thanks for your PR, @jsakamotoIGJP. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@jsakamotoIGJP

Copy link
Copy Markdown
Author

I know some CI checks failed. I'll fix them later.

@kotlarmilos
kotlarmilos requested a review from maraf September 15, 2026 10:40
Only the overloads without a token get DefaultAsyncTimeout, so this
matters on Blazor Server. Review feedback.
Window creates these objects and hands the same one to every caller, so a
dispose call from application code used to break the rest of the scope. The
interface is implemented explicitly now, following OwningComponentBase, and
disposal only releases the JS reference instead of poisoning the instance.
The scope still disposes everything through BrowserPlatform.
@jsakamotoIGJP

Copy link
Copy Markdown
Author

Aside: The build is still failing, but I'm sure that the only red item now is a flake that this change doesn't touch.

Here is what changed since I opened this, and what I need decisions on.

Fixed

  • The lock in Storage, which Javier asked about in the prototype review.
  • GetLengthAsync passed CancellationToken.None, and any token turns off the default JS interop timeout. It now uses the overload without a token.
  • Storage and Window implemented IAsyncDisposable publicly. Window creates them and hands the same instance to every caller, so a dispose from application code broke the rest of the scope. Both implement the interface explicitly now, and disposal only releases the JS reference.

Reverted, and this is the decision I need first

I temporarily reverted the adoption in ProtectedLocalStorage and ProtectedSessionStorage. Microsoft.AspNetCore.Components.Server is in the shared framework and cannot reference a package that is not, so every build leg failed. Moving these features into the shared framework would fix it, but that settles the packaging question on its own. @kotlarmilos, which way do you want to go?

Still open

  1. The E2E tests do not run in CI. Projects under testassets are excluded in eng/Build.props and added back one at a time, and I left PlatformTestApp.E2E.Tests out because this is a prototype. Tell me if you want it in the build.
  2. .github/skills/port-components-platform-api/SKILL.md came from the prototype branch, and I added the rules we learned in review. Keep it here, or drop it from this PR.

The branch is rebased on the current main with a linear history, and the first two commits are still by @kotlarmilos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants