Skip to content

[Blazor] WebAssembly service defaults template for Aspire integration #64574

Description

@javiercn

Summary

Create a blazor-wasm-aspire-servicedefaults project template (similar to maui-aspire-servicedefaults) that provides the necessary infrastructure for Blazor WebAssembly applications to integrate with Aspire.

Background

Currently, integrating Blazor WebAssembly with Aspire requires significant manual setup including:

  • Custom JS initializer to fetch configuration and inject environment variables
  • WebAssembly-compatible OTLP exporters (standard exporters use blocking patterns that deadlock in single-threaded WASM)
  • Service discovery and resilience configuration
  • Manual OpenTelemetry provider initialization (due to lack of IHostedService support)

The MAUI team has created maui-aspire-servicedefaults template that provides a similar experience. See: https://learn.microsoft.com/dotnet/maui/data-cloud/aspire-integration

Proposed Solution

Create a template that generates a *.ClientServiceDefaults project containing:

1. JS Initializer (*.lib.module.js)

export async function onRuntimeConfigLoaded(config) {
    const response = await fetch('/_blazor/_configuration');
    if (response.ok) {
        const serverConfig = await response.json();
        const envVars = serverConfig?.webAssembly?.environment;
        if (envVars) {
            config.environmentVariables ??= {};
            for (const [key, value] of Object.entries(envVars)) {
                config.environmentVariables[key.replaceAll(':', '__')] = value;
            }
        }
    }
}

2. ClientServiceDefaults Extensions

public static WebAssemblyHostBuilder AddBlazorClientServiceDefaults(this WebAssemblyHostBuilder builder)
{
    builder.ConfigureBlazorClientOpenTelemetry();
    builder.Services.AddServiceDiscovery();
    builder.Services.ConfigureHttpClientDefaults(http =>
    {
        http.AddStandardResilienceHandler();
        http.AddServiceDiscovery();
    });
    return builder;
}

3. WebAssembly-compatible OTLP Exporters

Custom exporters that use fire-and-forget async HTTP calls instead of blocking patterns:

  • WebAssemblyOtlpTraceExporter
  • WebAssemblyOtlpMetricExporter
  • WebAssemblyOtlpLogExporter
  • TaskBasedBatchExportProcessor<T>

4. Package References

  • Microsoft.Extensions.ServiceDiscovery
  • Microsoft.Extensions.Http.Resilience
  • OpenTelemetry.Extensions.Hosting
  • OpenTelemetry.Instrumentation.Http
  • OpenTelemetry.Instrumentation.Runtime
  • OpenTelemetry.Exporter.OpenTelemetryProtocol

Usage

dotnet new blazor-wasm-aspire-servicedefaults -n MyApp.ClientServiceDefaults
dotnet sln add MyApp.ClientServiceDefaults
dotnet add MyBlazorApp.csproj reference MyApp.ClientServiceDefaults

Then in the Blazor WASM Program.cs:

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Configuration.AddEnvironmentVariables(); // Until runtime support is added
builder.AddBlazorClientServiceDefaults();
// ...

Dependencies

This template's complexity can be reduced once the following are addressed:

  • Support hosted services in WebAssemblyHost #63637 - IHostedService support in WebAssembly (removes need for manual provider initialization)
  • Environment variables in IConfiguration by default (removes need for AddEnvironmentVariables())
  • Native WASM-compatible OTLP exporters in OpenTelemetry SDK

Related Issues

Part of .NET 11.0 Blazor + Aspire integration improvements

Metadata

Metadata

Assignees

Labels

area-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing oneon-roadmapListed on the current release roadmap

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions