Blazor and Runtime Framework SelfService - Record messed up

Posts   
 
    
AlexS
User
Posts: 14
Joined: 18-Apr-2016
# Posted on: 26-Mar-2021 09:24:46   

Hi,

I have been using LLBLGEN for many years and am very satisfied. So far I have only used it in the .net Framework 4 environment. But now I'm doing my first attempts with a "Blazor Server App". I stumbled upon very strange behavior and I hope you can help me find the problem.

My Blazor project is created with .net 5 and consists of only one single page, a form that saves data in the database. Not much more! As a basis I use the sample program from Microsoft and add a "Verladung" page to it.

The LLBLGEN project, generated with: LLBLGEN Version 5.8.0 Runtime Framework SelfService , General Netstandard Target Platform .net Standard 2.1

In "startup.cs", Method "Configure" i start my DB-Configuration (see last line):

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    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.UseHttpsRedirection();
                app.UseStaticFiles();
    
                app.UseRouting();
    
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapBlazorHub();
                    endpoints.MapFallbackToPage("/_Host");
                });
    
here we are===>            BahnCadConfiguration(); 
            }

And my Configuration-Method "BahnCadConfiguration()" looks like this (also in startup.cs):

public void  BahnCadConfiguration()
        {

    string conString = Configuration.GetConnectionString("BahnCad4ConnectionString");   //Reading from .json-Config-file          
    
    // siehe auch  https://www.llblgen.com/documentation/5.3/LLBLGen%20Pro%20RTF/using%20the%20generated%20code/gencode_runtimeconfiguration.htm
    
                RuntimeConfiguration.AddConnectionString("ConnectionString.SQL Server (SqlClient)", conString);
    
                RuntimeConfiguration.ConfigureDQE<SQLServerDQEConfiguration>(
                                             c => c.SetTraceLevel(TraceLevel.Verbose)
                                                 .AddDbProviderFactory(typeof(System.Data.SqlClient.SqlClientFactory))
                                                 .SetDefaultCompatibilityLevel(SqlServerCompatibilityLevel.SqlServer2012));
    
                //CatalogNameOverwrite
                var CatalogNameOverwrite = Configuration.GetSection("CatalogNameOverwrite");
                foreach (var dings in CatalogNameOverwrite.GetChildren())
                {
                    var oldString = dings.Key;
                    var newString = dings.Value;
                    RuntimeConfiguration.ConfigureDQE<SQLServerDQEConfiguration>(
                               c => c.AddCatalogNameOverwrite(oldString, newString));
                }
    } 

In my "razor-Page" (pages\verladung.razor) I get the username from AuthenticationStateProvider. This is the Primary-Key in my Database for user-table. With this Key i get via "fetchUsingPK" my users record and say "Hello User-Realname" to my User with the Realname saved in the database.

pages\verladung.razor:

     protected override async Task OnInitializedAsync()
            {
                var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
                var user = authState.User;
                if (user.Identity.IsAuthenticated)
                {
                    SessionController.UserKid = user.Identity.Name;   //Sessioncontroller see below
                }
                else
                {
    //other stuff
                    //userAuthenticated = "The user is NOT authenticated.";
                }
            }

static SessionController.UserKid-Property
    private static UserEntity currentUserEntity = new UserEntity();
     public static string _UserKid = "";
     public static string UserKid 
            {
                get {
                    return _UserKid;
                }
                set {
                    var kid = "";
         //----some code i removed because its scurity - stuff----
         //----- here kid - value is change to someone other
    
                    _UserKid = kid;
                    var vorhanden = currentUserEntity.FetchUsingPK(kid);
                    Console.WriteLine("User-ID = "+currentUserEntity.Id.ToString());
                    if (!vorhanden) //Wenn es diesen User gar nicht gibt!
                    {                    
                        noSuchUser = true;
                        currentUserEntity = new UserEntity();
                        _UserKid = "unbekannter User "+ kid;

                    }
                    else {
                        noSuchUser = false;
                    }
                }
            }

Everything works as expected when I test it locally. Now I've installed it on the IIS. When I test the program with a colleague at the same time, it happens that I am addressed by the colleague's name! It seems as if with simultaneous access the program uses the data set that actually belongs to my colleague!

Instead of "Hello Alex" I am greeted with "Hello Michael" - and Michael is a colleague who works with it at the same time.

The problem occurs very rarely and is difficult to reproduce because it appears to have to take place in exactly the same second.

Can you help me find the problem? Does this have anything to do with Singleton Dependency Injecton?

I'm a little at a loss - these are also my first steps with Blazor ...

Thank you for your help,

Alex

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 26-Mar-2021 09:40:38   

You store the userKid in a static variable, but as the app runs in a single process, every request will see that value as the same value as it's static... there's just 1 appdomain.

I think that's the first thing I'd look at, i.e. whether the userkid is indeed different for each user when they log in (I think it's the same, hence you get this problem). 'static' is something that should only be used for data that can be shared among all requests. I don't think user/session specific data falls in that category simple_smile

Frans Bouma | Lead developer LLBLGen Pro
AlexS
User
Posts: 14
Joined: 18-Apr-2016
# Posted on: 26-Mar-2021 12:06:00   

Hello Otis,

first: it's nice to meet you again after so many years! You have helped me so many times. And this time you probably saved me many, many hours of searching!

I thought a Blazor server instance runs like a normal application, completely separate from each other! It would never have occurred to me in my life that static variables could be read by all instances! So, of course, it doesn't make sense to save user authorizations in a static class! simple_smile

You can tell: I'm still at the very beginning of Blazor and also of web development! I just started one Week ago to learn Blazor, and it already works that I can access the database with LLBLGEN!

Many thanks Otis for your - as always - very valuable help! simple_smile

Greetings from Bavaria, Germany,

Alex