Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Shared state between server and client components in Blazor

$
0
0

My goal is to have two components with different render modes sharing state.

<CounterPresenter /> (InteractiveServer)

<Counter /> (InteractiveWebAssembly)

Is this possible?

enter image description here

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?


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>