I work on web application Blazor server side . I get error when apply session timeout reach to 20 minute then application will redirect to login page .
error happen on this block of code
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(20);
});
services.AddScoped<ISession>(_ => _.GetRequiredService<IHttpContextAccessor>().HttpContext.Session);
error
Category: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost
EventId: 111
SpanId: b5f359c71bdf98dd
TraceId: 55c402b51115a74fe957d0762f8e004f
ParentId: 0000000000000000
RequestId: 800002a3-0000-f500-b63f-84710c7967bb
RequestPath: /_blazor
TransportConnectionId: GD0qeN4kpoisoFqdq7Lm_Q
Unhandled exception in circuit 'fsJjR_i80e4-G8BcnIas7mkmnqTlTY5vpTXVNEzo_Rg'.
Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at UC.AppRepository.UI.Startup.<>c.<ConfigureServices>b__4_1(IServiceProvider _) in D:test repositoryBackupBlazorUC.AppRepository.UIStartup.cs:line 67
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass7_0.<CreateInitializer>g__Initialize|1(IServiceProvider serviceProvider, IComponent component)
at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance)
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
details
I apply session timeout after 20 minutes
1 – create js on wwwroot/js
file have function checkSessionTimeout
function checkSessionTimeout(currentUrl) {
var sessionTimeout = 20 * 60 * 1000; // 2 minutes in milliseconds
var lastActivity = new Date(Date.parse(sessionStorage.getItem("LastActivity"))); // get the last activity time from the client-side session
if (new Date() - lastActivity > sessionTimeout) {
/*console.log("reach 2 minutes")*/
sessionStorage.clear(); // clear the session storage
}
else
{
setTimeout(function () { checkSessionTimeout(currentUrl); }, 1000); // check again in 1 second
}
}
checkSessionTimeout(window.location.href);
2 – on page.razor
@inject ISession Session;
protected override void OnInitialized()
{
DateTime now = DateTime.Now;
string nowString = now.ToString("yyyy-MM-ddTHH:mm:ss");
JS.InvokeVoidAsync("sessionStorage.setItem", "LastActivity", now);
}
3 – after component load call function checkSessionTimeout
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var lastActivity = Session.GetInt32("LastActivity");
if ( TimeSpan.FromTicks(DateTime.Now.Ticks - lastActivity.Value) < TimeSpan.FromMinutes(20))
{
navigationManager.NavigateTo("/Login/Login");
return;
}
}
4- on _host file on last line on body
I add the following :
<script src="~/assets/js/checksessiontimeout.js"></script>
5-on startup class
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddHttpClient();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSession();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(20);
});
services.AddScoped<ISession>(_ => _.GetRequiredService<IHttpContextAccessor>().HttpContext.Session); line 67 that give me error
}
So How to solve or prevent this error from happen ?