bgmulinari / B1SLayer

A lightweight SAP Business One Service Layer client for .NET
MIT License
136 stars 47 forks source link

Login request with 30+ seconds response time #31

Closed it-AhmedTaha closed 1 year ago

it-AhmedTaha commented 1 year ago

Hi, I am trying to verify user credentials doing this

await _serviceLayer.Request("Login").PostAsync(new SapLogin { CompanyDB = _configuration["Sap:DatabaseName"], Password = request.Password, UserName = request.Username });

When user credentials are correct I get response in 3-8 seconds, however when the credentials are wrong response time is between 30-40 seconds. Am I doing anything wrong?

I was using normal http request and maximum time normally would be 6 seconds.

it-AhmedTaha commented 1 year ago

I've just realized that this isn't a problem. The default number of attempts is three, which results in a long response time.

it-AhmedTaha commented 1 year ago

Before I close this issue, is it possible to do a request without setting cookies or checking for active session?

bgmulinari commented 1 year ago

Hi, @it-AhmedTaha.

I see that you are trying to perform a login request, this isn't necessary as B1SLayer does that automatically.

I recommend you reading my blog post on SAP Community: https://blogs.sap.com/2022/05/23/b1slayer-a-clean-and-easy-way-to-consume-sap-business-one-service-layer-with-.net/

it-AhmedTaha commented 1 year ago

I understand that the B1SLayer application provides automatic handling of login and session. In my company, certain SAP users do not possess licenses, and therefore, we utilize a single licensed user to perform tasks and actions. Prior to granting access to users without licenses, it is necessary for me to verify the user credentials. Hence, I am wondering whether it is possible to perform this verification (login request) without setting cookies or checking for active session?

Right now I am doing this
await _serviceLayer.Request("Login").PostAsync(new SapLogin { CompanyDB = _configuration["Sap:DatabaseName"], Password = request.Password, UserName = request.Username }); it is working fine, but the if there is no session or the session has expired B1SLayer will automatically fire a request with the default licensed user to get a new session which will results in longer response time.

bgmulinari commented 1 year ago

Your scenario is very unusual. I guess you can do what you're doing, but there's no way to stop B1SLayer from validating the session before each request.

One thing you can do to improve the response time would be making sure you already have an active session before this credentials validation by calling serviceLayer.LoginAsync() beforehand. Also, you can lower the attempts to just 1 by setting the NumberOfAttempts property in your SLConnection instance.

Another thing to keep in mind is that unless you're caring about the license for compliance reasons, Service Layer doesn't require any license for the user, you just need a valid username and password and you can do anything, no license required.

it-AhmedTaha commented 1 year ago

Your scenario is very unusual. I guess you can do what you're doing, but there's no way to stop B1SLayer from validating the session before each request.

It is okay if I can not prevent B1SLayer from validating the session before each request. However after running some testing with this await _serviceLayer.Request("Login").PostAsync(new SapLogin { CompanyDB = _configuration["Sap:DatabaseName"], Password = request.Password, UserName = request.Username }); I get the error "Modifying this object is not permitted for current user" which is a normal behavior caused by user not having a license.

My question is, doing this

await _serviceLayer.Request("Login").PostAsync(new SapLogin { CompanyDB = _configuration["Sap:DatabaseName"], Password = request.Password, UserName = request.Username });

will generate a new session. Will B1SLayer set the new generated session as the default new session even without calling serviceLayer.LoginAsync().

Another thing to keep in mind is that unless you're caring about the license for compliance reasons, Service Layer doesn't require any license for the user, you just need a valid username and password and you can do anything, no license required.

I know Service Layer doesn't require any license for the user, but our SAP system will not accept any request from a user without a license.

bgmulinari commented 1 year ago

Hi, @it-AhmedTaha.

Performing a POST to the Login resource manually like you're doing is not going to set or replace the existing session that B1SLayer manages automatically.

it-AhmedTaha commented 1 year ago

Hi again, I am registering the SLConnection instance as a singleton and setting the number NumberOfAttempts to 1 like this

builder.Services.AddSingleton(_=> new SLConnection(
        $"https://{builder.Configuration["Sap:ServiceLayerBase"]}",
        builder.Configuration["Sap:DatabaseName"],
        builder.Configuration["Sap:Username"],
        builder.Configuration["Sap:Password"])
    {
        NumberOfAttempts = 1
    });

Some time I get this error "invalid session" , so I have to resend the request again. Is this happing because I am setting NumberOfAttempts to 1?

bgmulinari commented 1 year ago

I think it could be related, yes. I'll try to investigate this further, but for now setting NumberOfAttempts = 2 should prevent this.

Thanks for bringing this up.

it-AhmedTaha commented 1 year ago

I think it could be related, yes. I'll try to investigate this further, but for now setting NumberOfAttempts = 2 should prevent this.

Thank you. I will be waiting for your update or fix on the issue

bgmulinari commented 1 year ago

This should be fixed with version 1.3.1. Sorry for the delay on this release.

Thanks for your report, @it-AhmedTaha.