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.
Related
I want to insert some data into database when user cuts/exits the browser or tab.
This is the statement which I want to be executed.How is this possible
_objQ117.insert();
I'm in no way a C# guru, but I'll try to explain the general principle.
Browsers are pretty protective of the user's data these days, though there are possibilities.
You may use something akin to onunload or onclose to send an AJAX request to the server, executing the query.
However, support of this may be spotty in certain browsers. By sending AJAX requests, say every minute or so, the server will be aware that your client is still connected--until the requests stop. An AJAX request is nothing more than a standard HTTP request created by javascript and returned as a variable(i.e. without necessarily loading an entire page, as the server only returns a small amount of result data)
I have been publishing crystal Report and this is one of the most frequent error I get, if I close the tab which shows the report, my code keeps on running till the time report query (LINQ) runs in DAL.
Then my whole application freezes, is there a way by which I can stop the query of the closed tab report?
I just need a hint to do the same.
Thanks in advance, I was not able to search the solution on net as I was doubtful so as what should I ask.
You're asking for something unusual, so there is no usual way of doing it..
What I would try is to use jQuery and the unload event of the document to send a small REST request (if it's asp.net, then add an HTTP Handler -http://support.microsoft.com/kb/308001).
Add an identifier to the query string of the request and then at your server you can make sure the request was from the IP that matches the identifier of the client by checking Request.ServerVariables["REMOTE_ADDR"].
Then you're at your server, with an identifier and you made sure it's the client who sent it by unloading the page (closing the tab/browser).
As I'm not farmiliar with crystal resports, you should search for how it's possible to stop it: https://www.google.co.il/search?num=30&biw=1280&bih=699&q=stop+or+abort+a+crystal+report+asp.net&oq=stop+or+abort+a+crystal+report+asp.net
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.
On our .NET 3.5 website in c# a user clicks submit on our webpage, they are subscribed by email address to our reports. Unfortunately, this action takes about 5 minutes and the user has to sit and wait for confirmation. What I would like to do is change it so that when they click submit, they get a pop up that says they will be notified by email when their subscription goes through, meanwhile i would queue up the subscribe action somewhere else on the server so that it doesnt exist in the web code. Can you give me some ways to do this? The basic idea is that I want to split into two different lines of execution where one will allow them to still browse our website and the other will subscribe them. I was thinking split into a new thread but I think that the web code would still have to wait for that thread to finish before they could do anything else. I'm looking for ideas, preferably something that can run on the same server. thanks!
There's many options, but the basic approach will be to decouple the site from the provider. Instead you'll write out a record saying "User X is waiting to subscribe", a seperate process will then read the record and perform the actual subscription, while marking the record as "in-progress". Once the process has complete the record will again be updated with the completed information.
You can achieve this with databases, message queues, or other approaches. But fundamentally your site will only be responsible for creating the record and checking it's status--the actual interaction with the provider will be handled separately.
If you have something that takes this long and you want to true and ensure the action goes through, then your best bet is going to be to queue it up.
Basically, when they submit the request, store that in a database table and let them move on. Meanwhile, have another process that monitors that table to process the requests. When they come in just have this second process send the request on to the part that takes 5 minutes to complete.
Once it finishes, send them a "welcome to such and such email list" message. That will serve as their confirmation that it worked.
Jeff Atwood blogged on a relevant topic here a while back. Since you are using c#, I assume you're using ASP.NET and can take advantage of the cache mechanisms to kick off a periodic worker job. On the user's request, you can persist details of the subscription to some data store. In that job, you can examine the queue to determine what subscriptions need to be created and then execute them.
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
We currently host a lengthy form on our ASP.NET website, which makes use of a public facing facade WCF service to submit information over SSL into our network through a number of other facade services, etc.
We've experienced some issues with downtime on the service chain, and because of this some users have been very frustrated that they complete the lengthy form, only to find out after the fact that the service isn't up. Because of this, we are implementing a type of ping functionality on the form that will ping the service before the form is started, to ensure the service is up.
If the Ping() method is simply called during OnLoad of the form web page, there is potential for DOS attacks through for example a script that continually makes HTTP GET requests against the page.
My question is - From a conceptual level, what is the best way to ensure human interaction with the page while keeping it useable. For example, a CAPTCHA before the Ping() is called and form is started is way too intrusive even though it would be effective at ensuring the form is used properly. On the other hand simply allowing Ping() to fire OnLoad is far too risky for attacks.
One option I've considered is to have a button available to users which allows them to verify service availability and enable the form in one shot. This would at least be a balance between the two. I'm asking for your input on ideas for how best to balance this approach. Any asp.net, c#, or javascript/ajax based answers are fine.
Lastly - I also know there are flaws to this approach of checking service availability as there is no guarantee the service will be available by the time the form is filled out - but the decision has been made to use this approach so please keep your answers on point.
Thanks for the help and input in advance!
UPDATE 1:
In response to Josh's answer below - I should clarify that the form data submitted is sensitive and cannot be cached on the server or stored locally for later submission if the service fails. This is why it is very important to give the user a preemptive heads up. The issues we've had with the services are not intermittent so if the Ping() comes back true, there is an extremely good chance the user will not experience issues submitting the form a few minutes later.
UPDATE 2:
The Ping() Method is currently a server-side c# method, not javascript.
The public facing WCF service is IP-restricted to only allow requests from the public web server
Why don't you just call Ping() when the submit button is pressed and if the service doesn't respond then don't submit the form and show an error.
Something like this in jQuery. This assumses that Ping() returns true if the service is up, false otherwise:
$('#myformid').submit(function() {
var svcUp = Ping();
if(!svcUp)
alert("Sorry, there was an error submitting, please try again.");
return svcUp;
});
Unfortunately any public facing web service that has a low calling cost but high processing cost will be vulnerable to DOS attacks without some type of throttling.
Thankfully WCF has some useful settings for controlling throttling, take a look at MaxConcurrentCalls, MaxConcurrentInstances, and MaxConcurrentSessions
There is really no good solution on the client-side to prevent a DOS attack - I can create a script using your Ping js method that will call it a million times in a loop. You can prevent it on the server side though, by tracking calls per second form the same ip/session/user/otherclient-side identifier. If number of calls per second is over some reasonable limit, you temporarily ban that client.
You can look at http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx - scroll down to "Prevent Denial of Service (DOS) Attack" for an example
Call your function on page load and prior to the submit button. If you have any logging you are using you could insert into a log table for this particular aspx page view and include the IP address of the visitor. Set a threshold and if the IP makes more requests than what you required as proper usage, then put up some type of human-validation item.