Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session State is not working or Could not redirect to WebForms page. #382

Open
AjayKumar22n opened this issue Jul 22, 2023 · 33 comments
Open
Assignees
Labels
enhancement New feature or request needs author feedback The author of this issue needs to respond in order for us to continue investigating this issue.

Comments

@AjayKumar22n
Copy link

AjayKumar22n commented Jul 22, 2023

I am trying to migrate few of the pages from webforms application (Session oriented APP) to .Net core Blazor Server app (.Net 7), either I could not get the session object in the .net core or could not redirect to webforms page. Can you please suggest.

if I invoke RequireSystemWebAdapterSession() after MapBlazorHub middleware pipeline like below , I am able to set the session (System.Web.HttpContext.Current.Session!["sessionstring"] = "Temp Session";)

but System could not navigate from blazor to framework app.

### app.MapBlazorHub().RequireSystemWebAdapterSession();
app.MapRazorPages();
app.MapBlazorPages("/_Host");

app.MapReverseProxy();

suppose if I change code like below without RequireSystemWebAdapterSession, Navigation will work from Blazor Server app to framework app. But could not read or set the session in the core app, Current.Session is showing null.

app.MapBlazorHub();
app.MapRazorPages();
app.MapBlazorPages("/_Host");

app.MapReverseProxy();

if I use both then application is having ambiguous matching endpoint - which is not correct.
app.MapBlazorHub();
app.MapBlazorHub().RequireSystemWebAdapterSession();

here is the error from console:
System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (Bad Request).
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.SetOrReleaseSessionData(ISessionState state, CancellationToken cancellationToken)
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteSessionState.CommitAsync(CancellationToken token)
at Microsoft.AspNetCore.SystemWebAdapters.SessionMiddleware.ManageStateAsync(HttpContext context, SessionAttribute metadata)

I have set up unique apikey in both places, and tried with both latest adapters version 1.2.0 is also, if i use latest having different error.

Please see the complete code in the Program.cs here.

I have set up everything as described in the documentation -
var app = builder.Build();
app.UseStaticFiles();

app.UseForwardedHeaders();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

//app.UsePathBase("/" + pathBase);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseSystemWebAdapters();

//app.UseSession();
//app.UseCors(x => x.AllowAnyOrigin());
//app.UseRequestLocalization();
app.UseAuthorization();

//app.MapBlazorHub().BufferResponseStream().PreBufferRequestStream().RequireSystemWebAdapterSession();

// The following Require System Web Adapter session is required for MapBlazorHub to use the session context object.

app.MapBlazorHub().RequireSystemWebAdapterSession();
app.MapRazorPages();//.RequireSystemWebAdapterSession();
app.MapBlazorPages("/_Host");

app.MapReverseProxy();
app.Run();

please let me know if any additional details are needed.
appsettings.json: (reverse proxy)

"ReverseProxy": {
"Routes": {
"fallbackRoute": {
"ClusterId": "fallbackCluster",
"Order": "1",
"Match": {
"Path": "{**catch-all}"
}
}
},
"Clusters": {
"fallbackCluster": {
"Destinations": {
"fallbackApp": {
//This needs to be changed based on the environment.
"Address": "https://localhost/{aaa}"
}
}
}
}
}

@dotnet-policy-service dotnet-policy-service bot added the Needs: Triage 🔍 Label added to new issues which need Triage label Jul 22, 2023
@twsouthwick
Copy link
Member

@AjayKumar22n I'm a little confused by your example here. Can you clean it up a little so it's something we can easily reproduce?

@twsouthwick twsouthwick added the needs author feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Jul 26, 2023
@AjayKumar22n
Copy link
Author

Thank you so much for responding,

As per our Incremental Migration from ASP.Net webforms 4.8 framework to .Net 7 blazor server,
we need Three features to be done:

  1. Navigation between Framework web forms pages and Blazor server
  2. Share the session between both Framework app and Blazor server.
  3. we might need to use Third party controls like Telerik but those are rely on Blazor.server.js which is not loaded properly.

During this time:

  1. If I Use only the below line - Session is working in both apps but Navigation from Blazor Server to Webforms is not working.
    app.MapBlazorHub().RequireSystemWebAdapterSession();

  2. If I Use only app.MapBlazorHub() then only navigation is working, but Session is not working. Session itself is set to NULL
    image

  3. if I use Both lines - It should not be, both navigation and session are working but got the below error for initializers -
    Blazor.server.js is not loaded.

image

Here is the Middleware pipeline:
app.UseSystemWebAdapters();
app.MapBlazorHub();
//app.MapBlazorHub().RequireSystemWebAdapterSession();
app.MapRazorPages().RequireSystemWebAdapterSession();
app.MapBlazorPages("/_Host");
app.MapReverseProxy();

Our existing system requires this Incremental migration process, I apricate your support on this.

@twsouthwick
Copy link
Member

I think you're hitting the issue that is described here: https://learn.microsoft.com/en-us/aspnet/core/migration/inc/blazor?view=aspnetcore-7.0. Take a look and let me know if that solves it

@AjayKumar22n
Copy link
Author

AjayKumar22n commented Jul 26, 2023

I have gone through this and included as well,
here is the appsettings and extentions: Can you please help me on Do i need to make any changes here:
image

Extentions:
image

and Program.cs:

app.UseSystemWebAdapters();
//app.MapBlazorHub();
app.MapBlazorHub().RequireSystemWebAdapterSession();
app.MapRazorPages().RequireSystemWebAdapterSession();
app.MapBlazorPages("/_Host");
app.MapReverseProxy();

With all this configuration, Could nor redirect to Webforms page and question mark is appended at the end of URI, please see the screeshot for reference after I clik the webforms URL:

image

Can I push my code to github and share the link, plz?

@twsouthwick
Copy link
Member

Can I push my code to github and share the link, plz?

Yes - then I can check it out directly :)

@AjayKumar22n
Copy link
Author

Thank You for your valuable time to look into this, Here is the Git Hub path for the sample one.

https://github.com/AjayKumar22n/SystemWebAdapterWithSession

@twsouthwick
Copy link
Member

I'm not able to build it (can't find Telerik.UI.for.Blazor) - can you make it so it can build on any computer?

Taking a look, though, I think this is problem:

- app.MapBlazorHub().RequireSystemWebAdapterSession();
+ app.MapBlazorHub();
app.MapRazorPages();//.RequireSystemWebAdapterSession();
- app.MapBlazorPages("/_Host");
+ app.MapBlazorPages("/_Host").RequireSystemWebAdapterSession();
app.MapReverseProxy();

The call to .MapBlazorHub() will set up endpoints for static resources and connect/disconnect calls for the hub; but nothing for the pages. The .MapBlazorPages(...) call is where the actual pages are added as endpoints and where you want to add metadata.

@AjayKumar22n
Copy link
Author

AjayKumar22n commented Jul 27, 2023

I have tried the recommended steps, still the session is not working for the Razor pages.
Hey Sorry, I removed the Telerik stuff and pushed the code,

Can you please check out the latest of the master branch - https://github.com/AjayKumar22n/SystemWebAdapterWithSession
and help me? I tried with all combinations again, still I am having Session is null in the Context object.

@AjayKumar22n
Copy link
Author

Can you please confirm on the changes that i need to take care, Did I do any mistakes?

@AjayKumar22n
Copy link
Author

Hey Can you please let us know if we have any workaround for this to handle both Session state and navigation?

@twsouthwick
Copy link
Member

@AjayKumar22n I'm hitting something weird with your solution and it seems to crash VS whenever I try to load it. I'm going to try on a different machine....

@AjayKumar22n
Copy link
Author

@twsouthwick, Can you please use the following Repo: https://github.com/AjayKumar22n/MigrationUsingAdapters
I have remapped to different folder and tested it is working.

@AjayKumar22n
Copy link
Author

Hi @twsouthwick, It would really help us if you can you provide us any resolution.

@AjayKumar22n
Copy link
Author

Hey Can you please let us know if we have any workaround for this to handle both Session state and navigation?

@joperezr joperezr removed the Needs: Triage 🔍 Label added to new issues which need Triage label Aug 30, 2023
@joperezr joperezr added the enhancement New feature or request label Aug 30, 2023
@twsouthwick
Copy link
Member

Sorry for a delayed response. I think I understand the issue, and unfortunately, it's probably not an easy fix. In a Blazor server application, the existence of an HttpContext is not guaranteed and shouldn't be relied on (see dotnet/aspnetcore#17585 (comment)).

However, some good news: with the updates coming in .NET 8 for true server side rendering of blazor, an HttpContext will be available there to enable this scenario (may need some updates on our side, but we think it will be better). It'll be available in RC2 release thanks to this PR: dotnet/aspnetcore#50253.

If you want to try that out (via nightly builds), please let us know if there's anything we need to expose/enable here to integrate with it.

@pockets3407
Copy link
Contributor

@AjayKumar22n Were you able to get it working using .NET 8?

@twsouthwick I've tried and the session is no longer null, but I keep getting the following errors:

  1. Getting the session in Home.razor if set from web forms
System.Net.Http.HttpRequestException: Response status code does not indicate success: 500 (Internal Server Error).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.GetSessionDataAsync(String sessionId, Boolean readOnly, HttpContext callingContext, CancellationToken token)
   at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.CreateAsync(HttpContext context, SessionAttribute metadata)
   at Microsoft.AspNetCore.SystemWebAdapters.SessionMiddleware.ManageStateAsync(HttpContext context, SessionAttribute metadata)
   at Microsoft.AspNetCore.SystemWebAdapters.PreBufferRequestStreamMiddleware.InvokeAsync(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)      
  1. Setting the session in Home.razor
System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (Bad Request).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.SetOrReleaseSessionData(ISessionState state, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteSessionState.CommitAsync(CancellationToken token)
   at Microsoft.AspNetCore.SystemWebAdapters.SessionMiddleware.ManageStateAsync(HttpContext context, SessionAttribute metadata)
   at Microsoft.AspNetCore.SystemWebAdapters.PreBufferRequestStreamMiddleware.InvokeAsync(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Program.cs:

using BlazorApp1Net8.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpForwarder();
builder.Services.AddSystemWebAdapters()
    .AddJsonSessionSerializer(options =>
    {
        options.RegisterKey<string>("test-value");
    })
    .AddRemoteAppClient(options =>
    {
        options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
        options.ApiKey = "C63B2E0B-72CF-4AF6-83CD-B9A3A84DACF4";
    })
    .AddSessionClient();

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseAntiforgery();
app.UseSystemWebAdapters();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .RequireSystemWebAdapterSession();

app.MapForwarder("/Scripts", app.Configuration["ProxyTo"]).Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);
app.MapForwarder("/Content", app.Configuration["ProxyTo"]).Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);
app.MapForwarder("/About", app.Configuration["ProxyTo"]).Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);
app.MapForwarder("/Contact", app.Configuration["ProxyTo"]).Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);
app.Run();

Global.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;

namespace WebApplication1
{
    public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            // Code that runs on application startup
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
                .AddJsonSessionSerializer(options =>
                {
                    options.RegisterKey<string>("test-value");
                })
                .AddRemoteAppServer(options =>
                {
                    options.ApiKey = "C63B2E0B-72CF-4AF6-83CD-B9A3A84DACF4";
                })
                .AddSessionServer();
        }
    }
}

Home.razor:

@page "/"
<PageTitle>Home</PageTitle>

<h1>Hello, @TestValue!</h1>

Welcome to your new app.

@code {
    [CascadingParameter]
    public HttpContext? HttpContext { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ((System.Web.HttpContext)HttpContext).Session["test-value"] = "From Blazor";
        TestValue = ((System.Web.HttpContext)HttpContext).Session["test-value"]?.ToString();

        await base.OnInitializedAsync();
    }

    public string? TestValue { get; set; }
}

@pockets3407
Copy link
Contributor

It seems to be working now. I am not sure what I did, but I am not longer getting any error messages. I tried recreating the problem with the above code and it works fine now.

@twsouthwick
Copy link
Member

@pockets3407 this is great to hear! Would you be up for submitting a sample to the repo with this new set up?

@pockets3407
Copy link
Contributor

@twsouthwick Sure, I can submit something once .NET 8 has been released

@twsouthwick
Copy link
Member

Great! Our repo is already targeting. Net 8 so no need to wait if you have something.

@pockets3407
Copy link
Contributor

pockets3407 commented Nov 15, 2023

@twsouthwick Sorry about the delay. I am in the middle of adding the sample here: https://github.com/pockets3407/systemweb-adapters/tree/blazor-session-sample. I am having issues getting it working.

  1. Sessions are null in Static render mode
    This code isn't executed if I put a breakpoint inside. I think this is related to changes made with SessionStateBehavior. State is never set and always set to null
    .AddRemoteAppClient(options =>
    {
        options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
        options.ApiKey = builder.Configuration["RemoteAppApiKey"];
    })

2. I am not sure if this is intended, but when using Server render mode for a component, HttpContext is null

EDIT: I realized that HttpContext is not intended to work with Server render mode.

@twsouthwick
Copy link
Member

Thanks @pockets3407 - I'll take a look in the morning

@pockets3407
Copy link
Contributor

@twsouthwick I was wondering if there was any update on this. I have noticed #453 and #455 have been created and I think these are related.

@erpardeepkaushik
Copy link

Hello, i tried an example but seems .net8 and yarp 1.3 is not working together or there is a bug in VS2022. i always get the session values null in asp.net core app. but downgrading to all packages of system web adaptors to 1.2 works seamlessly. please advise what could be the issue. please find the repos links with ver 1.3

https://github.com/erpardeepkaushik/TestWebCore
https://github.com/erpardeepkaushik/TestWeb

@erpardeepkaushik
Copy link

Hello @twsouthwick, @AjayKumar22n @pockets3407 is there any solutions exists for this issue. I tried another example where session sharing is working between ASP.net web form app and Razor Core App. but not working with Blazor App. Also if we enable all below settings then it works with Blazor but with lot of error in yarp(no redirecting properly only one Blzoor app tab work at time.)

app.MapBlazorHub().RequireSystemWebAdapterSession();
app.MapRazorPages().RequireSystemWebAdapterSession();
app.MapBlazorPages("/_Host").RequireSystemWebAdapterSession();

Could you please advise a solutions. we have an urgent project and we stuck here now. SystemWebAdapter V1.3 is not working at all. we are working with SystemWebAdapter1.2 at the moment with NET 8.

@pockets3407
Copy link
Contributor

pockets3407 commented Jan 11, 2024

@twsouthwick I submitted by Pull Request for my sample. The only issue I have found is that I get an exception that breaks navigation. This occurs when I navigate from an InteractveServer page (Counter) to a static page (Home, Weather).

@erpardeepkaushik
Copy link

@pockets3407 @twsouthwick its couple of months now and we are still waiting as we are stuck while upgrading our Webform app to asp.net core. please release the next version asap.

@pockets3407
Copy link
Contributor

@erpardeepkaushik With the current workaround that I described in my sample, I did not have any issues using 1.4 SystemWebAdapters to transfer session from WebForms to Blazor.

        app.UseWhen(
            (context) => context.Request.Method != HttpMethods.Connect,
            (builder) => builder.UseMiddleware<SessionLoadMiddleware>());

Besides the workaround, I don't know if there are any plans to fix this.

@erpardeepkaushik
Copy link

hi @pockets3407 and @twsouthwick , i still unable to get access of session from blazor app. Could please have a look in my Proram.cs file. in Controller i can getting the values. but in blazor it always return null.

Proram.cs ======================

using BlazorTestCore.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpForwarder();

builder.Services.AddSystemWebAdapters()
.AddJsonSessionSerializer(options =>
{
options.RegisterKey("UserId");
})
.AddRemoteAppClient(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
options.ApiKey = builder.Configuration["RemoteAppApiKey"];
})
.AddSessionClient();

// Add services to the container.
//builder.Services.AddControllersWithViews();

builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

//app.UseRouting();

app.UseAntiforgery();

//app.UseAuthorization();
//app.UseSystemWebAdapters();

app.UseWhen(
(context) => HttpMethods.IsConnect(context.Request.Method) == false,
appbuilder => appbuilder.UseSystemWebAdapters());

//app.MapDefaultControllerRoute()
// .RequireSystemWebAdapterSession();

app.MapRazorComponents()
.AddInteractiveServerRenderMode()
.RequireSystemWebAdapterSession();

app.MapForwarder("/{**catch-all}", app.Configuration["ProxyTo"]).Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);

app.Run();

Proram.cs end ======================

Blazor component============

@code {
private int currentCount = 0;

[CascadingParameter]
public HttpContext? HttpContext { get; set; }
string UserId { get; set; }

private void IncrementCount()
{

    var webHttpContext = ((System.Web.HttpContext)HttpContext);
    if (webHttpContext != null && webHttpContext.Session != null)
    {
        UserId = webHttpContext.Session["UserId"]?.ToString() ?? string.Empty;
    }      
}

}

Thanks

@pockets3407
Copy link
Contributor

@erpardeepkaushik HttpContext is only available in static SSR. Try checking it when the page is pre-rendered in OnInitalizedAsync instead of the button click. If you need any session information after pre-rendering, I would take a look at:
https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/additional-scenarios?view=aspnetcore-8.0#pass-tokens-to-a-server-side-blazor-app

@erpardeepkaushik
Copy link

@pockets3407 thanks for a quick reply, I am using InteractiveServerRenderMode(prerender: false) so its null even on OnInitializedAsync , is there any way to add it in interactive SSR or InteractiveServerRenderMode(prerender: false) mode
please advise.

@pockets3407
Copy link
Contributor

@erpardeepkaushik Take a look at the link I provided in my last post. HttpContext cannot be passed to interactive SSR, but the data can be retrieved before the circuit is opened and used.

In my application, I am using PersistingApplicationState while pre-rendering to store the data I need

@erpardeepkaushik
Copy link

@pockets3407.

I am getting below error on server, while the session access from webform app to razor page is working perfectly on local machine. any suggestion on this.

sample code

if (((System.Web.HttpContext)HttpContext).Session != null)
{
var UserId = ((System.Web.HttpContext)HttpContext).Session["UserId"].ToString();
}

Category: Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer
EventId: 2
SpanId: 630613ad124bc281
TraceId: 9129471e9d0f9a267aa04154f28ff77a
ParentId: 0000000000000000
RequestId: 400010ee-0804-eb00-b63f-84710c7967bb
RequestPath: /Login

Connection ID "16933543412991267053", Request ID "400010ee-0804-eb00-b63f-84710c7967bb": An unhandled exception was thrown by the application.

Exception:
System.Net.Http.HttpRequestException: Response status code does not indicate success: 405 (Method Not Allowed).
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.SetOrReleaseSessionData(ISessionState state, CancellationToken cancellationToken)
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteSessionState.CommitAsync(CancellationToken token)
at Microsoft.AspNetCore.SystemWebAdapters.SessionLoadMiddleware.ManageStateAsync(HttpContext context, ISessionStateFeature feature)
at Microsoft.AspNetCore.SystemWebAdapters.PreBufferRequestStreamMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.SystemWebAdapters.SessionStateMiddleware.InvokeAsync(HttpContext context)
at Microsoft.Extensions.DependencyInjection.RegisterAdapterFeaturesMiddleware.InvokeAsync(HttpContext context)
at Microsoft.Extensions.DependencyInjection.RegisterAdapterFeaturesMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs author feedback The author of this issue needs to respond in order for us to continue investigating this issue.
Projects
None yet
Development

No branches or pull requests

5 participants