Creating your first In Memory State Container with Blazor Server

Web technology has come along way in the relatively recent past. With the surge in popularity of SPAs and Javascript Frameworks a lot of developers have come to expect certain functionality out of the box. Blazor Server being a stateful application framework offers us a lot of functionality missing from the days of old stateless web. One of these features is In Memory State Management. This allows any razor component that injects the State Container to access properties in an almost ‘global’ fashion.

This tutorial will show you how to implement a bare bones state container that uses a MudBlazor DatePicker component. Keep in mind, this method doesn’t persist the data indefinitely and shouldn’t be used for any sensitive/complex data. It will only persist as long as the user is connected to the server via a circuit. People familiar with Sessions in Asp.net MVC Session['StartDate'] may find this is as a good replacement in Blazor Server.

If you’re interested in a more robust way to track state throughout your application you should look into Database State Management, Distributed Cache State Management, Browser Storage State Management, or fluxor.

Advantages

Disadvantages

We start by creating a new class called DateFilterStateContainer, this class is responsible for persisting a StartDate and EndDate DateTime property throughout the application. 

DateFilterStateContainer.cs

				
					public class DateFilterStateContainer
    {
        private DateTime start;
        private DateTime end;
        public DateTime StartDate
        {
            get => start;
            set
            {
                start = value;
                NotifyStateChanged();
            }
        }
        public DateTime EndDate
        {
            get => end;
            set
            {
                end = value;
                NotifyStateChanged();
            }
        }
        public event Action OnChange;
        private void NotifyStateChanged() => OnChange?.Invoke();
    }
				
			

Wire up the State Container for dependency injection.

Program.cs

				
					builder.Services.AddScoped<DateFilterStateContainer>();
				
			

Here we use a MudBlazor DatePicker to set values for the State Container to store via the SetState method.

The SetState method simply binds the values from the DatePicker to the State Container.

StateHasChanged subscribes to the OnChange action delegate in the DateFilterStateContainer class. This is what notifies the State Container of changes from the UI. The State Container stores these values in memory to be retrieved at a later time.

Lastly when the user navigates away from this component the Dispose method is executed, unsubscribing the OnChange delegate. More info here on how that works.

Home.razor

				
					@page "/"
@using Core.StateManagement

<PageTitle>State Management</PageTitle>

<MudDatePicker Label="Start" @bind-Date="StartDate" />
<MudDatePicker Label="End" @bind-Date="EndDate" />
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@SetState">Set State</MudButton>

@code {
    [Inject]
    DateFilterStateContainer StateContainer { get; set; }
    DateTime? StartDate { get; set; }
    DateTime? EndDate { get; set; }
    
    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
        StartDate = DateTime.Now.AddDays(-3);
        EndDate = DateTime.Now.AddDays(3);
    }
    void SetState()
    {
        StateContainer.StartDate = (DateTime)StartDate;
        StateContainer.EndDate = (DateTime)EndDate;
        Console.WriteLine($"State Set! {StateContainer.StartDate} - {StateContainer.EndDate}");
    }
    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}

				
			

Home.razor

Here we access the StartDate and EndDate properties contained within the DateFilterStateContainer.

AnotherComponent.razor

				
					@page "/another-component"

<h1>What are the values in our state container?</h1>
@if(StateContainer is not null)
{
    <label>Start:</label> @StateContainer.StartDate
    <br />
    <label>End:</label> @StateContainer.EndDate
}
				
			

AnotherComponent.razor

AnotherComponent.razor.cs

				
					using Core.StateManagement;

public partial class AnotherComponent
{
    [Inject]
    DateFilterStateContainer StateContainer { get; set; }
    
    protected override async Task OnInitializedAsync()
    {
        StateContainer.OnChange += StateHasChanged;
        base.OnInitialized();
    }
    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}
				
			

In-Memory State Management is one of the options for state management in Blazor Server. It has some advantages and disadvantages that you need to consider before choosing it for your application. 

Want to learn more?

IHttpClientFactory vs. HttpClient

Why should you use IHttpClientFactory The main reason to use IHttpClientFactoryinstead of HttpClient directly is to manage the life cycle of HttpClient instances. HttpClient was designed to be instantiated once and reused throughout the application life cycle. If you continually instantiate new HttpClients you may unnecessarily be squandering resources. Another use case is for simplicities…

Read more