I have below ItemAccessHub implementation to lock rows that are being edited by users to avoid multiple edits on a same row.
public class ItemAccessHub : Hub
{
private static readonly ConcurrentDictionary<string, (string ConnectionId, string Module, string Username)> RowLocks = new();
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var rowId = Context.GetHttpContext().Request.Query["row-id"].ToString();
if (RowLocks.TryRemove(rowId, out var value) && value.ConnectionId == Context.ConnectionId)
{
Clients.Others.SendAsync("RowUnlocked", rowId);
}
return base.OnDisconnectedAsync(exception);
}
public Task LockRow(string rowId, string module, string username)
{
RowLocks[rowId] = (Context.ConnectionId, module, username);
return Clients.Others.SendAsync("RowLocked", rowId, username);
}
public Task UnlockRow(string rowId)
{
if (RowLocks.TryRemove(rowId, out var value) && value.ConnectionId == Context.ConnectionId)
{
return Clients.Others.SendAsync("RowUnlocked", rowId);
}
return Task.CompletedTask;
}
}
Below is the code on a page where hubconnection gets set:
hubConnection = new HubConnectionBuilder()
.WithUrl(UriHelper.ToAbsoluteUri("/itemaccesshub"))
.Build();
hubConnection.On<string, string>("RowLocked", (rowId, username) =>
{
rowLocks[rowId] = username;
InvokeAsync(StateHasChanged);
});
hubConnection.On<string>("RowUnlocked", rowId =>
{
rowLocks.Remove(rowId);
InvokeAsync(StateHasChanged);
});
await hubConnection.StartAsync();
Now everything else works a part from browser closure or page refresh, means row stays lock forever in these 2 instances.
I want to implement row lock in a way that if 1 user is editing it is locked for other user. If locked user closes or refresh browser the locked row should get released.
user23341174 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.