Invoke code-behind method when browser is closing - c#

I need to find a way to intercept browser closing and invoke a metod to update a record with several information about logged user in DB. It's very important this record is updated when the user is logging-out or when he close the browser. Obviously when the user clicks 'Logout' I handle the update in the server-side event, but what if the user simply exit from browser?
Someone suggest to use the window.onbeforeunload event and make an asynchronous call to some WS or WebMethod to execute the code, but this doesn't convince me at all: the problem with onbeforeunload is that it shows a confirm prompt. I need to avoid this message and simply invoke the method.
So I'm wondering if there is a 'server-side' solution without using ajax or javascript.
For example... a way to trigger some event on session abandon or session clear, or some other way to solve this problem just working on code-behind...

There is no way you could have a server-side solution to know something that happens in the client browser.

I do not believe there is any way to do what you need server-side only. Client side is the only way. Server has no way of knowing when browser window was closed, this is limitation of HTTP protocol.

Yes, you can put an event in the Global.AsaX which will fire when the session ends. Now if you need data from the client to update the db etc., you'll need a way of getting it there, but if not, then the Session_End will do the trick.
Note: Session end is slightly different than the browser closing, so it this will depend on what you want the event firing to do.
How to handle session end in global.asax?

I'd like to find a 'server-side' solution without using ajax or
javascript.
I suspect that it's impossible with that requirement.
Maybe you could do something like:
Have a hidden IFRAME on the page
Set the Refresh header on this IFRAME (or use a META element) to contact the server every couple of seconds
If you do not hear from the client for some period of time, assume the browser has been closed.
However, I imagine that this solution will not scale well.

Have you considered something like signalr? I use it to detect when someone has a record open.
public class ChatHub : Hub
{
public override Task OnDisconnected()
{
Broadcaster.Disconnected(Context.ConnectionId);
return base.OnDisconnected();
}
}

For the moment I changed radically the approach to my problem.
To update pending rows I implemented a timed job using Quartz.NET framework, that runs every night.

Related

Prevent from multiple form submitions without javascript

I've got an Asp.net MVC action that creates user account(after input validation). And a View containing registration form that invokes this action. While action validates input, user is left with webbrowser waiting for server response and click submit button a few more times. This creates several accounts. Is there a way to prvent user from form resubmition without javascript. I cannot use javascript in this project it is intended for non javascript browsers. Or can you suggest(server) other solution?
EDIT:
This form request use POST method
JavaScript is not allowed because this Web Application is aimed for special web browsers for people with disabilities that do not support javascript
You have to handle the situation on the server-side then, there's no way around that.
There are 3 options that come to my mind atm:
create a cookie and for each submit check if it exists
similar, but using a session object
before creating a new account, always check if the user exists in the database. THIS should be a no-brainer anyway!
You can add a unique hidden token as part of the form. This token can also be saved as part of the session on the server.
When the user posts the form on the first action, the token is validated and a flag set to indicate the request is being processed. The action processed and results presented. If, while awaiting results, the user attempts to repost the request, the token validation fails as the request is still being processed.
On a side node, the main reason people continuously click is that there is no feed back on whether the request was received by the server or not. To this affect, it might be better to redirect the user to an interim page that shows the request is being processed. Which in conjunction with the above can be used to show the request progress and redirect to the appropriate page when completed.
Of-course, you should also consider making the process a bit lighter. So, that the system can respond quickly to input rather than making the user wait.
Is it a requirement to use MVC? I think you can accomplish something similar using WebForms. When the user submit the request, in the code behind you can disabled the submit button like this:
btnSubmit.Enabled = false;
But if MVC is a must be, #walther answer would be correct

FiddlerCore - Multithreading webbrowser, getting same session

I am with a very specific question, and I'll try to explain the best I can. I'm using windows forms, with webbrowser, multithread and fiddler.
My application executes different forms in multiple threads. There is an webbrowser on each form, that is running at the same time as the other webbrowsers on the other forms.
Each of them uses fiddlercore, and some of them navigate to the same website, searching for some information.
In the fiddlercore code, I use the event FiddlerApplication_AfterSessionComplete to capture all the traffic from the website (on each of the webbrowsers).
The main problem is that fiddler doesn't distinguish from which thread I'm navigating, so sometimes it takes the information that's supposed to be on another thread to the form that's navigating to the same page, but searching another things.
So, what I really need is a way to check if the Session I got from fiddler is the same as launched from that specific form.
If you need, I can post some code, but I don't think it's actually necessary.
I appreciate any help.
I don't know fiddlercore but from documentation on FiddlerApplication_AfterSessionComplete should be a Fiddler.Session object with an oRequest property of type ClientChatter. ClientChatter has a headers property,
So my suggestion is to add a Custom Header with a unique identifier (thread number.. guid..) in the request and check for this header when FiddlerApplication_AfterSessionComplete is fired to match Request / Response.

Fire a server side method on aspx page immediately after an interrupt

Imagine that I have an aspx page that is home page of my site and users spend their times at it. Now I need after occurring an occurrence, this page become update. For example if a new user joined to website all users see it on their home page.
I use a ajax timer for solving my problem and one method is called every one second and if my site has been changed, I can show it to users. But this is no good solution. Please tell me how I can fire a method immediately after an interrupt like above example.
(I think yahoo mail use this way too when we get some new emails)
Thanks for any help.
you can make the current thread 'sleep' entil new changes comes up. Each web request correspont to a thread. and you need to use a global collection to keep track of all currenlt sleeping thread.
var lastMsgTime=Global.NewMsgTime;
while(true){
Thread.Sleep(300);
if(!Response.IsClientConnected||RequeGlobal.NewMsgTime!=lastMsgTime){
lastMsgTime!=Global.NewMsgTime;
break;
}
}
you'll still be using ajax on client side.

ASP.Net - How can we update row in database table if browser is closed

I have an asp.net web-forms application which is using entity model. When a users logs in, we create a row in user_session table with timein. and when user logs out we update that row and put timeout.
Now problem is, when user closes the browser without logging out, how can we update the row in user_session table?
You can't. There is no way of the server being notified that a browser has been closed by the client. The best you could do is to schedule some job on your SQL Server which runs and updates rows. You may try also subscribing for the Session_End event in Global.asax but be careful because this event might never be triggered if you are using an out-of-process session.
Short answer is: You can't. That's why you shouldn't try to do such a silly thing.
The longer answer is: You have to put up with the delayed response of a session timeout. That could be a significant amount of time. In Global.asax there is an event called Session_End, which you can hook to do what you want.. but it won't show when the user closed their browser. It will only fire when the session has ended, which by default is 20 minutes after the last request. And that's only if it's an in-memory session and the process hasn't crashed.
The better solution is to just run a job every so often to clear the users online table. That solves the problem regardless, but requires more work for your job to figure out what to remove.
In your Global.asax.cs, you can code that in the Session_End event. It will not happen till the session timeout (default 20 minutes), but it will happen. You will likely want to delete any existing records on Application_Start and/or Application_End events (the Application_End event does not execute when the computer or web process crashes so best to use Application_Start) to make sure you start off fresh when the web application loads.
You can use the Event Session_End in the Global.asax.
There may be a delay between the browser closing and the actual session timeout on the server depending on your session settings.
I guess should be scheduled job that will close expired sessions like in AspState.
You can take a look into AspState database stored procedure DeleteExpiredSessions to see what you need to do. This procedure job with name ASPState_Job_DeleteExpiredSessions call each minute to close sessions.
Try the below code.
On the form_load event in every page, write the below code.
Response.AppendHeader("Refresh", "60; URL=../default.aspx")
Default session time out is 20 minutes and I am using "60" seconds for this demo. If there is no activity in this period of time, then it goes back to the default or home page and we send a key to update the database "session key" or any other tag. This way we can possibly know the activity of the user or member.
This worked for me.

Running server-side function as browser closes

Background: I'm creating a very simple chatroom-like ASP.NET page with C# Code-Behind. The current users/chat messages are displayed in Controls located within an AJAX Update Panel, and using a Timer - they pull information from a DB every few seconds.
I'm trying to find a simple way to handle setting a User's status to "Offline" when they exit their browser as opposed to hitting the "Logoff" button. The "Offline" status is currently just a 1 char (y/n) for IsOnline.
So far I have looked into window.onbeforeunload with Javascript, setting a hidden form variable with a function on this event -> Of course the trouble is, I'd still have to test this hidden form variable in my Code-Behind somewhere to do the final Server-Side DB Query, effectively setting the User offline.
I may be completely obfusticating this likely simple problem! and of course I'd appreciate any completely different alternative suggestions.
Thanks
I suspect you are barking up the wrong tree. Remember, it is possible for the user to suddenly lose their internet connection, their browser could crash, or switch off their computer using the big red switch. There will be cases where the server simply never hears from the browser again.
The best way to do this is with a "dead man's switch." Since you said that they are pulling information from the database every few seconds, use that opportunity to store (in the database) a timestamp for the last time you heard from a given client.
Every minute or so, on the server, do a query to find clients that have not polled for a couple of minutes, and set the user offline... all on the server.
Javascript cannot be reliable, because I can close my browser by abending it.
A more reliable method might be to send periodic "hi I'm still alive" messages from the browser to the server, and have the server change the status when it stops receiving these messages.
I can only agree with Joel here. There is no reliable way for you to know when the HTTP agent wants to terminate the conversation.

Categories

Resources