I have a web app that has rows of data which has a column called active
. If a row is inactive the row is still presented to the user.
The client wants to have a localStorage
toggle option to hide inactive rows from the view. Since all of my logic happens in the controller using the localStorage
to filter html rows just doesn't seem proper. (Hiding elements with javascript vs simply filtering the data at the controller level).
If I cannot add a new column in the database for a "hide inactive items" feature--what would be the best solution to add a toggle inactive items
in the entire application?
I was thinking of creating a claim:
new Claim(ClaimTypes.UserData, "true", ClaimValueTypes.Boolean), // Hide inactive rows
And later in the application:
internal static bool showInactiveRows(ClaimsPrincipal user)
{
var showInactive = true; // Default hide inactive rows
var identity = (ClaimsIdentity)user.Identity;
if (identity != null)
{
// Get claim containing our setting
var _showInactiveRows = identity.FindFirst(ClaimTypes.UserData);
if (_showInactiveRows != null)
// Set the session value to the model
showInactive = bool.Parse(_showInactiveRows.Value);
}
return showInactive;
}
internal static async void setHideInactiveRows(ClaimsPrincipal user, bool hideInactiveRows)
{
var identity = (ClaimsIdentity)user.Identity;
if (identity != null)
{
// Get claim containing our setting
var _showInactiveRows = identity.FindFirst(ClaimTypes.UserData);
identity.RemoveClaim(_showInactiveRows);
identity.AddClaim(new Claim(ClaimTypes.UserData, hideInactiveRows.ToString(), ClaimValueTypes.Boolean));
/*if (SignInManager.IsSignedIn(User)) // Need to call this to refresh claims without logging out
{
var user = await UserManager.GetUserAsync(User);
await SignInManager.RefreshSignInAsync(user);
}*/
}
}
Then when I'm grabbing data:
var hideInactiveRows = UserClaims.showInactiveRows(User);
if(hideInactiveRows)
{
FarmList = await _context.Farms
.Where(i => i.Active == hideInactiveRows) // Active = true show only active rows
.OrderBy(g => g.Name)
.ToListAsync();
} else {
FarmList = await _context.Farms
.OrderBy(g => g.Name)
.ToListAsync();
}
However this too doesn't seem right to me.
Is there a better way to update and pass data inside the application on a per user basis?
CodePudding user response:
To anyone who needs a solution in the future I tried the query param checking in the OnGet() method but this was taking too long as I have to modify 50 pages.
The solution I came up with is to simply just create a Singleton Service:
public interface IUserMemStorage
{
// Using concurrent dictionary as it's thread safe
ConcurrentDictionary<int, string> UserHideInactiveRowStore { get; set; }
// Create other tmp storages here
}
// Note: Only register this interface as a singleton
// I created a new interface to explicitly mention singleton
public interface IUserMemStorageSingleton : IUserMemStorage { }
public class UserMemStorage : IUserMemStorageSingleton
{
public UserMemStorage()
{
UserHideInactiveRowStore = new();
}
public ConcurrentDictionary<int, string> UserHideInactiveRowStore { get; set; }
}
then later register the service in the Startup.cs
.
Now on the pages I need this on I can simply use the dependency injection container and check if I should show/hide the results based on the userId
. No need to modify any backlinks or different navigation pages as the bool
is stored in the thread safe dictionary. :)