PeakSWC.RemoteWebViewService
10.0.15
See the version list below for details.
dotnet tool install --global PeakSWC.RemoteWebViewService --version 10.0.15
dotnet new tool-manifest
dotnet tool install --local PeakSWC.RemoteWebViewService --version 10.0.15
#tool dotnet:?package=PeakSWC.RemoteWebViewService&version=10.0.15
nuke :add-package PeakSWC.RemoteWebViewService --version 10.0.15
RemoteBlazorWebView.Wpf.BlazorWebView
RemoteBlazorWebView.Wpf.BlazorWebView is a powerful control based on the .NET 9 Blazor WebView Control for WPF applications. It allows you to interact with the user interface of a program developed using the BlazorWebView WPF control through a web browser by leveraging a cloud-based server.
The RemoteBlazorWebView.Wpf.BlazorWebView control facilitates remote interaction with your application's user interface by setting up a server (RemoteWebViewService) in the cloud and connecting your browser to it.
As a drop-in replacement for the Microsoft.AspNetCore.Components.WebView.Wpf.BlazorWebView control, RemoteBlazorWebView.Wpf requires only minimal changes to your existing application to enable remote control capabilities. This makes it an efficient and convenient solution for extending your application's functionality.
RemoteBlazorWebView.WindowsForms.BlazorWebView
RemoteBlazorWebView.WindowsForms.BlazorWebView is a robust control built on the .NET 9 Blazor WebView WinForms Control, designed for Windows Forms applications. It allows you to engage with the user interface of a program created using the BlazorWebView WinForms control through a web browser, utilizing a cloud-based server.
The RemoteBlazorWebView.WindowsForms.BlazorWebView control enables remote interaction with your application's user interface by establishing a server (RemoteWebViewService) in the cloud and directing your browser to connect with it.
As a seamless replacement for the Microsoft.AspNetCore.Components.WebView.WindowsForms.BlazorWebView control, RemoteBlazorWebView.WindowsForms.BlazorWebView necessitates only minimal adjustments to your current application to empower remote control capabilities. This makes it an effective and user-friendly option for enhancing your application's features.
Demo Video
![]()
Usage instructions
You do not need to build this repo unless you want to customize the RemoteWebViewService. Run the following command to install the RemoteWebViewService
dotnet tool update -g PeakSWC.RemoteWebViewService --version 9.*-*
Switching between local and remote
Mark the window with [RemoteBlazor(nameof(MyBlazorWebView), ...)] and call the generated InitializeRemoteBlazor() after InitializeComponent(); see the source generator's README.
Sharing control (owner, remote user, viewers)
A session can be shared between the person at the machine and a remote user, with control handed back and forth.
Roles. A session supports exactly these participants:
| Role | How they join | What they can do |
|---|---|---|
| Owner (one) | The app's own window shows the controlling page /app/<id>?role=owner (BlazorWebView.NavigateToUrl). |
Starts in control. Can give control to the remote user and can always take it back. |
| Remote user (one) | Opens the read-only link /mirror/<id> (requires EnableMirrors). The remote user is the first non-owner connection in the session. |
Watches until the owner gives control; then drives the app and can give control back. Gets the remote user's end of the voice call when voice is on. |
| Viewers (any number) | Open the same /mirror/<id> link after the remote user. |
Read-only. They are never given control, cannot take it, and have no voice. |
Only one connection controls the app at a time; the relay ignores input from everyone else, and control is never given to a second remote user. If the remote user leaves, the next-oldest viewer becomes the remote user. If the connection in control closes, control returns to the owner while the owner is connected; otherwise the session ends.
Supervised or unattended. By default a session is supervised: the owner starts in control and decides when to give it. Add &control=remote to the owner's page address (/app/<id>?role=owner&control=remote) for an unattended session: the remote user is given control as soon as they join, and the owner can still take it back. The app chooses, so its users can pick the policy that suits them.
Session controls bar. Each browser draws its own bar (status, Give control / Take control, Copy link for the owner, voice buttons). Put an empty <div id="rbwv-session-controls" data-share-link="true"></div> where the bar should sit in your layout; without it the bar floats bottom-right. A floating bar only appears when the session has an owner or a voice call, so an app that uses neither looks as it did before. A dot at the start of the bar is lit while anyone is connected remotely; hovering over it says how many. The bar calls the two parties "The host" and "Remote user"; name them for your app with data-host-name and data-remote-name on the placeholder (for example data-remote-name="The technician"). Restyle with the rbwv-control-* / rbwv-voice-* classes. window.RemoteControl exposes the same state for a custom UI.
Restart button. Add data-restart="true" to the placeholder to give whoever has control (and the owner, always) a Restart app button, with a confirm step. The relay sends the app the same Refreshed event a browser refresh raises, so an app that restarts itself there needs nothing else; every browser page then waits for the new copy and loads again by itself. The button never appears without the placeholder.
With the source generator. [RemoteBlazor(nameof(RemoteBlazorWebView), ShareControl = true)] (or Unattended = true) generates this setup; see the generator's README.
Upgrade the relay and the packages together. Sharing control needs relay and packages 10.0.15 or later on both sides. With an older relay the Give control / Take control buttons do nothing. An app on older packages keeps working against a 10.0.15 relay.
Remote components. A remote component's frame follows the page it is on: it is usable in the browser that controls the app and read-only in the others, and moves with control. Viewers always see it read-only.
Sign-in on the relay
By default the relay asks nobody to sign in: a session's pages open for anyone who has the link. The
Authorization:Provider setting (environment variable Authorization__Provider) chooses otherwise:
| Provider | What it does |
|---|---|
None (default) |
No sign-in. |
AzureB2C |
Azure AD B2C sign-in (settings: the AzureAdB2C section and Secret). In every relay build except the native one (-c NoAuthorization). A relay built with -c Authorization uses it without the setting. |
Fake |
For tests: the request names its user as name;group1,group2 in the X-Rbwv-Fake-User header, the fake-user query value or the rbwv-fake-user cookie. The relay refuses to start with it outside the Development environment. |
With sign-in on, a session's pages (/app, /mirror, /<id>, /status, /wait) open for a signed-in user whose groups
include the session's Group, and for the app's own window, which needs no account: it opens its page with the owner key
(below). Each connection's signed-in name is in the roster. A relay hosted in-process takes a provider directly:
RemoteWebViewServerOptions.Authorization. A provider is an IRelayAuthorization.
Owner key. With ShareControl, the app makes a secret for the session (OwnerKey) and opens its own page as
/app/<id>?role=owner&key=<key>. Only that page is the owner; ?role=owner added to any other link is ignored.
ParticipantsChanged on the control reports who is in the session, their names and who has control.
Samples
Check out the tutorial at https://github.com/budcribar/RemoteBlazorWebViewTutorial
| 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. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 11.0.0-rc2 | 108 | 10/25/2026 |
| 10.0.15 | 0 | 11/11/2026 |
| 10.0.14 | 59 | 11/8/2026 |
| 10.0.13 | 263 | 10/19/2026 |
| 10.0.0-preview5 | 450 | 6/14/2025 |
| 10.0.0-preview4 | 450 | 5/14/2025 |
| 10.0.0-preview3 | 442 | 4/12/2025 |
| 9.0.22 | 63 | 11/6/2026 |
| 9.0.21 | 204 | 10/15/2026 |
| 9.0.6 | 644 | 6/15/2025 |
| 9.0.5 | 671 | 5/14/2025 |
| 9.0.4 | 656 | 4/12/2025 |
| 9.0.2 | 654 | 2/16/2025 |
| 9.0.1 | 882 | 1/18/2025 |
| 9.0.0 | 783 | 11/14/2024 |
| 9.0.0-rc2.1 | 213 | 11/1/2024 |
| 8.0.11 | 1,008 | 11/14/2024 |
| 8.0.10 | 1,197 | 10/10/2024 |
| 8.0.8 | 1,286 | 8/20/2024 |
Based on maui 10.0.15
Changes since 10.0.14
Release workflow publishes to NuGet when dry_run is off (trusted publishing, nuget-org approval)
10-client test waits 2 minutes before attaching browsers again (idle sessions must survive)
Server stats tests: the app's own blazor.modules.json is served now (2 bytes fewer per client)
ParticipantsChanged needs relay 10.0.15
Merge PR #85 (module, JS, relay, lifecycle, generator and system test fixes)
README and release notes: sign-in providers, owner key, ParticipantsChanged
Authorization is injected, not compiled in: None, Fake (tests) and AzureB2C providers
Tests: owner URL carries the key; spoofed-owner test waits for the roster
WinForms: OwnerKey is not a designer property
WIP: owner key, names in the roster, ParticipantsChanged, session group check
Remove UTF-8 BOM from embedded blazor.modules.json and clear CS8602 warnings
Use bundled protoc 3.x binary in scripts/protoc.js on Linux CI
Fix bugs across module, JS, relay, lifecycle, generator, and system tests
Browser swarm keeps 300 separate clients, spread over 10 Chromium processes
Fix RunTests.ps1 packaging/tool issues, concurrent browser tests, and MSB3277 warnings
RunTests: -NoBuild runs the tests on what the last run built
Lost-connection test cuts the viewer's connections itself
A lost connection is shown and a /mirror page comes back; unattended hand-over retried; frames follow the latest control change
Web.JS test file as EditWebView writes it
EditWebView keeps this repository's own changes across a run
Upstream source from MAUI 10.0.130 and aspnetcore 10.0.15 (EditWebView run)
Document EditWebView in the release process.
EditWebView: ask for tag dates only on the wanted major version, and print progress
EditWebView prints what a run changed; Web.JS/src and test no longer git-ignored
update packages
EditWebView: fall back to the GitHub CLI sign-in when GITHUB_PAT is not set
Microsoft 10.0 libraries to 10.0.15, SDK 10.0.404; EditWebView re-applies the Web.JS patches
Control test: a browser that has not been told yet is 'not agreed', not an error
Restart test: wait for the restart to start before waiting for the page to return
RunTests: -Filter for a partial browser run; restart test keeps the bar in view
Agent: hand the requester the session's join link
Generator: voice, run-time choices, app-supplied startup values, and a restart that survives a stuck window
Library: a restart request still restarts an app whose UI thread is stuck
Session bar: opt-in Restart button
Shared control: one change of controller at a time
Voice: a mirror page gets the remote end whenever nobody holds it
Relay: every write to the app's stream goes through one guarded method
Shared control: a message from before a hand-off can no longer replace a real one
RunTests: quote the -p: switch so PowerShell passes it whole
RunTests: run every test project, quick suites first
BugBountyTests: the mirror-scroll test ignores the control notices browsers are now sent
ControlTransferTests: the fake browser stream accepts the relay's token overload
Tests for sharing control: relay policy, render acks, URL loading, and end-to-end browser tests
Agent protocol: 'requester' instead of 'technician'; consent fallback is 'Someone'
Unattended address is control=remote; neutral wording in comments, package notes and the voice prompt
Session bar: connection dot, neutral wording, host/remote names on the placeholder
Package release notes for 10.0.15
10.0.15: generator ShareControl/Unattended, compatibility fixes, docs
Build warnings: WebView2 WPF reference, AOT-safe relay JSON/config, RS1032
Unattended sessions: ?control=technician gives the technician control on joining
Remote component frames follow control; roster in join order; document roles
Remote component frames: role follows the page kind, not who has control
Full list: https://github.com/budcribar/RemoteBlazorWebView/compare/10.0.14...eedda77cab529ca84113b6b515e9c62b6969e76d