adamfoneil / Dapper.CX

A Crud library based on Dapper
MIT License
8 stars 1 forks source link

make it possible to prefix keys used with DbDictionary with a user name #39

Closed adamfoneil closed 3 years ago

adamfoneil commented 3 years ago

This would make DbDictionary more easily usable as a state dictionary in Blazor. By automatically prefixing keys with the current user name, you'd get automatic user isolation of state data. This came up as I worked through Blazor state options described here. I tried browser storage, and there are complications regarding pre-rendered html. I knew that DbDictionary was an option, but it needs an easier way to isolate content by user.

adamfoneil commented 3 years ago

Got this working with a new FormatKey virtual method.

Implementation I'm using looks like this:

public class StateDictionary : DbDictionary<string>
{
    private readonly string _userName;

    public StateDictionary(DapperCX<int, User> data) : base(data.GetConnection, "dbo.StateDictionary")
    {
        _userName = data.User.Name;
    }

    protected override string FormatKey(string key) => $"{_userName}-{key}";

    protected override TValue Deserialize<TValue>(string value) => JsonSerializer.Deserialize<TValue>(value);

    protected override string Serialize<TValue>(TValue value) => JsonSerializer.Serialize(value);
}

In use, it looks like this. The point of this is to remember the state of filter and paging controls

image

without some kind of state management, navigating around a Blazor app causes components to revert to their default state, meaning that filters, sort options, and page controls all lose their values. This would be very poor user experience to have to keep starting over with every interaction.

@inject StateDictionary State

const string storageKey = "company-query";

protected override async Task OnInitializedAsync()
{
    query = (await State.GetAsync<CompanyQuery>(storageKey)) ?? new CompanyQuery() { DataOwnerId = Data.User.DataOwnerId, Page = 0 };
    // some code omitted for clarity
}
adamfoneil commented 3 years ago

Broadly speaking, I'm not sure there's a compelling reason to use DbDictionary as an ISession replacement. I think I learned an aversion to using Session for anything from pre-.NET Core days. But I actually like .NET Core ISession functionality.