Coordinate with Aspire to consume the Blazor Gateway as a bundled binary (replace Gateway.cs.in)
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
## Summary
Once [#67094](https://github.com/dotnet/aspnetcore/issues/67094) ships an official `mcr.microsoft.com/dotnet/blazor-gateway` image, we should coordinate with the Aspire team to remove the inlined [`Gateway.cs.in`](https://github.com/microsoft/aspire/blob/main/src/Aspire.Hosting.Blazor/Scripts/Gateway.cs.in) source template from `Aspire.Hosting.Blazor` and replace it with the precompiled gateway binary.
This tracks the ASP.NET Core side of the work (publishing the gateway in a shape Aspire can consume); the Aspire side will need its own follow-up issue in `dotnet/aspire`.
## Motivation
Aspire currently ships the Blazor gateway as a **source file** (`Gateway.cs.in`) inside `Aspire.Hosting.Blazor`. At AppHost startup, Aspire writes the file to disk, invokes `dotnet run` against it, and orchestrates the resulting process. This:
- Recompiles the gateway every time an Aspire AppHost runs.
- Forks the gateway implementation between ASP.NET Core (`Microsoft.AspNetCore.Components.Gateway`) and Aspire (`Gateway.cs.in`), so fixes have to be applied in both places.
- Cannot trivially pick up gateway updates without a corresponding `Aspire.Hosting.Blazor` release.
Once ASP.NET Core ships the gateway as a redistributable artifact (which it already does — the package's `tools/blazor-gateway.dll` layout is consumable by anyone willing to extract it), Aspire can bundle the precompiled binary and exec it directly.
## Proposal
`Aspire.Hosting.Blazor` adopts the same pattern they already use for shipping the Aspire Dashboard binaries — bundle the gateway `tools/` payload inside `Aspire.Hosting.Blazor.nupkg` itself, then resolve the path at runtime from the integration assembly's location.
### Sketch on the Aspire side (for context, not part of this work)
```xml
```
At runtime:
```csharp
var gatewayDll = Path.Combine(
Path.GetDirectoryName(typeof(BlazorGatewayResource).Assembly.Location)!,
"..", "..", "tools", "blazor-gateway", "blazor-gateway.dll");
```
(Aspire already does the equivalent for the dashboard — exact path layout TBD on their side.)
### Why Shape B (bundle inside the Aspire package)
Discussed in [#67094](https://github.com/dotnet/aspnetcore/issues/67094) and on the original prototype thread. The alternatives:
- **Transitive ``** (let the gateway flow from `Aspire.Hosting.Blazor` to the AppHost): works, but exposes the gateway as a transitive dependency in the user's AppHost (`dotnet list package --include-transitive`). Cosmetic leak.
- **`dotnet tool exec`** (requires `PackAsTool=true`): rejected, see [#67092](https://github.com/dotnet/aspnetcore/issues/67092) — NU1212 makes `PackAsTool` mutually exclusive with `` consumption, which would break the standalone WASM template.
- **Container image** ([#67094](https://github.com/dotnet/aspnetcore/issues/67094)): the right answer for production / K8s / ACA scenarios but forces Docker on dev machines for local F5.
- **Bundle inside `Aspire.Hosting.Blazor`**: user adds `Aspire.Hosting.Blazor` and gets everything — no extra package, no transitive surprises, no Docker requirement for local F5. Aspire owns the snapshot version. Already the pattern Aspire uses for other bundled binaries.
## ASP.NET Core side work (this issue)
The gateway's existing package shape is **already compatible** with Shape B — no source changes are required in `dotnet/aspnetcore`. Specifically:
- `tools/blazor-gateway.dll` flat layout is preserved.
- All transitive runtime dependencies (OpenTelemetry, YARP, Service Discovery, Polly, HealthChecks) are already under `tools/`.
- `tools/blazor-gateway.runtimeconfig.json` points at `Microsoft.AspNetCore.App 11.0.0` with `rollForwardOnNoCandidateFx: 2`.
The only ASP.NET Core side commitments we're making by accepting this proposal:
- [ ] **Treat the `tools/` layout as a public contract** for at least one supported consumer (Aspire). Document the shape (folder structure, dll names, runtimeconfig framework references) so it can't be silently broken.
- [ ] **Ensure the gateway nupkg restores cleanly without `compile`/`runtime`/`build` assets** (it already does, since there's no `lib/` and the only `build/` content is the WASM-template `.targets` file which Aspire excludes).
- [ ] **Coordinate the version bump cadence** with the Aspire team so `MicrosoftAspNetCoreComponentsGatewayVersion` in `Aspire.Hosting.Blazor` can be advanced predictably (every preview / GA).
- [ ] Optionally, add a small smoke test in our build that performs the same extract-and-run pattern Aspire will use, so a future refactor of the package layout can't break Aspire silently.
## Sequencing
1. [#67048](https://github.com/dotnet/aspnetcore/pull/67048) merges — service-defaults template + current gateway improvements.
2. [#67094](https://github.com/dotnet/aspnetcore/issues/67094) lands in `dotnet/dotnet-docker` — `mcr.microsoft.com/dotnet/blazor-gateway` image published.
3. **This issue** — file an `dotnet/aspire` companion issue requesting Aspire bundle the gateway via Shape B and delete `Gateway.cs.in`. Document the `tools/` contract on our side.
## References
- [#67032](https://github.com/dotnet/aspnetcore/issues/67032) — original service-defaults template update
- [#67048](https://github.com/dotnet/aspnetcore/pull/67048) — current gateway / template PR
- [#67092](https://github.com/dotnet/aspnetcore/issues/67092) — investigation of `PackAsTool` (closed as won't-fix, NU1212 blocker)
- [#67094](https://github.com/dotnet/aspnetcore/issues/67094) — official Blazor Gateway container image
- [`Aspire.Hosting.Blazor/Scripts/Gateway.cs.in`](https://github.com/microsoft/aspire/blob/main/src/Aspire.Hosting.Blazor/Scripts/Gateway.cs.in) — the inlined source template to be replaced
- [`Aspire/playground/BlazorStandalone/BlazorStandalone.ClientServiceDefaults`](https://github.com/microsoft/aspire/tree/main/playground/BlazorStandalone/BlazorStandalone.ClientServiceDefaults) — reference Aspire integration
Contributor guide
Assessment
This issue has not been assessed yet.