If client is idling much time, it will pop-up login dialog when retrieve the data. How to reconnect again without dialog? Should I set “KeepAlive” in “TROWinInetHTTPChannel”?
KeepAlive is a property that controls whether to use HTTP Keep-Alive to keep the connection alive between requests. If enabled (true) , once a request is made and a connection is established, this connection is kept open and used for future requests.
If disabled, the connection is closed, and a new connection is created for future requests.
Since establishing a connection is - relatively speaking - a costly and resource intensive operation for the network, compared to sending small amounts of data, it is recommended to keep this option enabled for optimal performance, if requests to the server are done relatively frequently.
For Keep-Alive to work, the option must be supported and enabled on both client and server.
The feature you need is a
Each client channel exposes
OnLoginNeeded event. This event is raised when server cannot find a session corresponding to the current user. This happens when a user did not log in or the user’s session has been expired.
So one can handle this event to perform a silent relogin.
Note: Please remember that such relogin operation creates a new user session, so all values stored in the old user session are lost.
Code sample of such event handler:
procedure TClientDataModule.ClientChannel_OnLoginNeeded(Sender: TROTransportChannel; anException: Exception; var aRetry: Boolean); var lUserId: String; lPassword: String; lStorePassword: Boolean; begin // Performing login if (Self.LogOn(gUserId, gPassword)) then begin aRetry := true; Exit; end; lUserId := ''; lPassword := ''; lStorePassword := gStorePassword; if not Login(lUserId,lPassword, lStorePassword) then ShowMessage('Login cancelled'); gUserId := lUserId; if lStorePassword then gPassword := lPassword else gPassword := ''; gStorePassword := lStorePassword; if Self.LogOn(lUserId, lPassword) then begin aRetry := true; end else begin ShowMessage('Login failed'); end; end;
Thanks for your explanation.
I checked my coding is as same as your sample code. That means I need to set Keep-Alive to true that will not show the login dialog again if idling much time.
Keep-Alive is not related to sessions at all. It is a Http-transport level feature and does not affect logging it anyhow.
So let’s start from the beginning.
Could you check the following?
- Does this event handler get called at all?
- Is there a code path that tries to relogin silently using stored user Id and password?
- If 2 is true then does this code get executed during a relogin attempt for expired session?
Point 1 & 2 is running normally and set the default user id and password in coding. I set “Keep-Alive” to true and idling the application overnight. It can running without ask the id and password.
FTR, two things should be taken as completely separate:
a) the server asking the client for login
b) the client app asking the user for login
part (a) will happen all the time. essentially whenever the app hasn’t communicated for 20 minutes (or whatever your session timeout iOS set to). part (b) ideally should only happen once (once per app launch, or maybe even once per install, depending on your security model).
when (a) happens the very first time, your app should ask the user, and the your client app should store it (securely), either in memory or (again, thats your call) persistently for subsequent launches, if you like). when (a) happens again (and it will), just reuse the stored credentials.
The dialog is asking by Server side. User will be confuse this dialog because they don’t know why application ask “User Name” and “Password” again.
Thats the point. you should only show this dialog in two cases
- you don’t have a username and password yet.
- you have, but calling Login() on the server with the username and password you have failed.
in all other cases, when you get the
OnLoginNeeded event, just call Login on the server with the username and password you already have, without asking the user again.
does that make sense?
Username and password is assigned by application when it is running. If idling over a long time, then system will pop-up login dialog when user click the application’s feature. The dialog has “User Name” & “Password” data. User click “OK” button and application resume.
I’m not sure i understand. Remoting SDK will not show a dialog on its own, so its up ton you whether to show this dialog if its not needed, nor not?
Could you please show your code that handles the OnLoginNeeded event?
The following code is using your testcase.zip before. I will using Keep-Alive for workaround first. I will prepare the testcase for simulate my question later.
procedure TClientDataModule.ClientChannel_OnLoginNeeded(Sender: TROTransportChannel; anException: Exception; var aRetry: Boolean); var lUserId: String; lPassword: String; lStorePassword: Boolean; begin // Performing login if (Self.LogOn(gUserId, gPassword)) then begin aRetry := true; // e.LoginSuccessful := true; Exit; end; lUserId := 'sys'; lPassword := 'sys'; lStorePassword := gStorePassword; if not Login(lUserId,lPassword, lStorePassword) then ShowMessage('Login cancelled'); gUserId := lUserId; if lStorePassword then gPassword := lPassword else gPassword := ''; gStorePassword := lStorePassword; if Self.LogOn(lUserId, lPassword) then begin aRetry := true; // e.LoginSuccessful := true; end else begin ShowMessage('Login failed'); end; end;
Could you send the entire project to support@ ?
Thanks in advance
Sorry that I can’t send the project for you. Because it links to MSSQL DB and it has many modules. I will complete my system migration first and prepare the testcase for you later.
I’m using the following code in Login.FormShow. It has the following error. Then I click continue. It will pop-up the login dialog. “User Name” and “Password” are hardcode in “ClientChannel_OnLoginNeeded” event.
Okay, but why don’t you just remove the code that does that? If the login is hardcoded anyways (not sure if thats a good idea, but thats a separate matter), why have this code at all? Why even have the form What am I missing?
Yes. Something is missing without tell you. In “Login Screen”, I need to connect the system DB that handle the multi languages information. So I need to hardcode the login information. Then it needs to connect different DB Servers. Before I asked about how to connect the different connections. But DA without this function. So I created a procedure that pass the connection parameter and FillWithDASql. Or I misunderstand the “Logon(ConnID,ConnID)” function?
ClientDataModule.ExecSQL(‘SYS’,SYSUser_no, tbl_master, DASQL, nil);
ClientDataModule.ExecSQL(‘SYS’,SYSUser_no, Clientdatamodule.tbl_Department, DASQL, nil);
Ok, but can’t you simply not call
I need not to call TLoginForm.Show(). I’m using the following code that will show the “Login Form” first.
Application.ShowMainForm := False;
Application.MainFormOnTaskbar := True;