My goal is to have two components with different render modes sharing state.
<CounterPresenter /> (InteractiveServer)
<Counter /> (InteractiveWebAssembly)
Is this possible?
This is what I have so far:
Program.cs
using BlazorApp1.Client.Services;using BlazorApp1.Components;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents();builder.Services.AddHttpClient();builder.Services.AddScoped<CounterStateService>();builder.Services.AddControllers();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){ app.UseWebAssemblyDebugging();}else{ app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseAntiforgery();app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorApp1.Client._Imports).Assembly);app.MapControllers();app.Run();Program.cs (Client)
using BlazorApp1.Client.Services;using Microsoft.AspNetCore.Components.WebAssembly.Hosting;var builder = WebAssemblyHostBuilder.CreateDefault(args);builder.Services.AddScoped(sp => new HttpClient { });builder.Services.AddSingleton<CounterStateService>();await builder.Build().RunAsync();CounterStateService.cs
namespace BlazorApp1.Client.Services{ public class CounterStateService { public int CurrentCount { get; set; } }}CounterStateController.cs
using BlazorApp1.Client.Services;using Microsoft.AspNetCore.Mvc;namespace BlazorApp1.Controllers{ [ApiController] [Route("[controller]")] public class CounterStateController(CounterStateService counterStateService) : ControllerBase { [HttpGet(nameof(GetCounterState))] public IActionResult GetCounterState() { return Ok(counterStateService.CurrentCount); } [HttpGet(nameof(IncrementCounterState))] public IActionResult IncrementCounterState() { counterStateService.CurrentCount = counterStateService.CurrentCount + 1; return Ok(counterStateService.CurrentCount); } }}CounterPresenter.razor
@using BlazorApp1.Client.Services@rendermode InteractiveServer@inject CounterStateService CounterStateService<span>Current count: @(CounterStateService is null ? "Loading" : CounterStateService.CurrentCount)</span>Counter.razor
@page "/counter"@rendermode InteractiveAuto@inject HttpClient HttpClient<PageTitle>Counter</PageTitle><h1>Counter</h1><p>Current count: @(CurrentCount is null ? "Loading..." : CurrentCount)</p><button class="btn btn-primary" @onclick="IncrementCountAsync">Click me</button>@code { public int? CurrentCount { get; set; } protected override async Task OnInitializedAsync() { CurrentCount = await HttpClient.GetFromJsonAsync<int>("https://localhost:7095/CounterState/GetCounterState"); } private async Task IncrementCountAsync() { CurrentCount = await HttpClient.GetFromJsonAsync<int>("https://localhost:7095/CounterState/IncrementCounterState"); }}The issue I have is that CounterStateService.CurrentCount is always 0 when IncrementCounterState is incrementing the count. It seems CounterStateController receives a new instance of CounterStateService each time the endpoint IncrementCounterState is hit. I am obviously doing something wrong.
However, is what I am trying to achieve possible?
