Skip to content

Coordinate with Aspire to consume the Blazor Gateway as a bundled binary (replace Gateway.cs.in) #67095

Description

@javiercn

Summary

Once #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 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)

<!-- Aspire.Hosting.Blazor.csproj -->
<PackageReference Include="Microsoft.AspNetCore.Components.Gateway"
                  Version="$(MicrosoftAspNetCoreComponentsGatewayVersion)"
                  PrivateAssets="all"
                  GeneratePathProperty="true"
                  ExcludeAssets="build;buildTransitive;runtime;compile;native" />

<Target Name="_BundleBlazorGateway" BeforeTargets="GenerateNuspec">
  <ItemGroup>
    <None Include="$(PkgMicrosoft_AspNetCore_Components_Gateway)\tools\**\*"
          Pack="true"
          PackagePath="tools\blazor-gateway\" />
  </ItemGroup>
</Target>

At runtime:

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 and on the original prototype thread. The alternatives:

  • Transitive <PackageReference> (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 — NU1212 makes PackAsTool mutually exclusive with <PackageReference> consumption, which would break the standalone WASM template.
  • Container image (#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 merges — service-defaults template + current gateway improvements.
  2. #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

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-blazorIncludes: Blazor, Razor Components

    Type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions