Call a method on browser closing - c#

I am facing an issue in my application when a user directly clicked on browser close [X] button. Browser can be IE, Chrome, Mozilla, Firefox and many more.
What I want to do:
1. as soon as user hits [X] button of browser, need to set their status as logged off in database for which we have a method in Login.aspx file which is within the master page.
2. We do not have any Logoff feature in the application
I will be thankful if anyone suggests a solution to call the method which sets the user status as logged off from master page.
Thanks in advance.

This is not possible due to the nature of http connections and the web in general. Simply have a timeout (eg. 10 minutes) after which a user gets logged out automatically.

Javascript has an onunload function, so you could do:
<body onUnload="doFunction()">
However this, and other methods are going to be unreliable (I'm not sure in which specific instances it is fired) as it would be a security concern allowing websites to have access to perform many functions on browser onunload.
The best solution would be to have cookies/sessions automatically time out, and also to educate users to logout if the system is sensitive.

If you are using jQuery you could work with
$(window).unload( function () {
$.ajax({ **your params** });
} );
But I have to agree with Tom Gullen here - your sessions should timeout eventually.

Related

.NET C# Session Variable Not Updating in Safari Browser

I'm having an issue with storing a Guid key in session with Safari. The code works perfectly fine in IE, Chrome, and Firefox, but for some reason Safari is not updating the session variable. Here's an example of the problem:
sessionOutputOne.InnerHtml = Session["TopicId"]; //Old topic ID d158e4f2-c0ac-41ce-8798-e936afaf67f8
Session["TopicId"] = someobject.GuidId.ToString();
sessionOutputTwo.InnerHtml = Session["TopicId"]; //Shows new topic Id f72850a4-c29f-4d1e-ab46-7939c097a002
If I refresh the page, the first Session["TopicId"] output shows the new Topic Id (f72850a4-c29f-4d1e-ab46-7939c097a002) in every browser EXCEPT Safari, which continues to show the old id (d158e4f2-c0ac-41ce-8798-e936afaf67f8).
I have eliminated the following possibilities based on other stackoverflow threads:
There is no page redirect in effect after setting the session variable.
The session variable is not being set in an iframe, but there are iframes in the site for google products.
I am not trying to store anything complicated in this session variable, just a guid converted to string.
Cookies are not disabled in Safari, and I have customers on other Safari browsers experiencing the same issue.
Additional clue on this: the session variable does successfully set when I turn on Safari "Private Browsing" mode.
Thank you in advance for any insights as to what else I can look into.
Update:
So the plot grows thicker. I have found a Response.Redirect in my root Default.aspx.cs file that redirects logged in users to a sub-directory. Commenting out this redirect gets the session working properly; however, it does not appear that the redirect is even being hit. If I replace the redirect with Response.End() to kill the response, everything in the site continues to work fine--only the homepage dies if you hit it directly instead of redirecting logged in users to their content.
Solution
Thanks to Steven's persistent assistance with my debugging, I was finally able to at least figure out what is happening, if not why. For some reason, Safari touches our root Default.aspx file when loading our Browse Topic page (possibly behind the scenes, somehow). The Default.aspx was redirecting back to the browse topic page without a query string variable. The Browse page would then clear the session variable to set it to the default topicid. Very convoluted, I know. My solutions was to check for the Session["TopicId"] in Default.aspx and let it redirect to the Browse page with the querystring variable since I could not figure out how to prevent Safari from hitting this page.
Have you tried clearing the cookie and testing that? See if you can clear out the cookie.
Session.Remove("TopicId");
If you CAN clear the cookie, try resetting the cookie after the clear to the new value.
Session.Add("TopicId",someObject.GuidId.ToString());
UPDATE BASED ON USER UPDATE:
Based on your, have you tried:
Response.Redirect(url, false);
Adding that parameters (false) does not abort the thread and continues executing code that is on that thread. Let me know the results.

Why IE Keeps sessions alive?

Hy all!
I'm developing a MVC 4.0 web application with C# and came accros the following error.
In major browsers (Chrome, Mozilla Safari, etc...) when i click logout in my web application it does the correct, logout the current user.
When i do the same operation on IE, dosen't work, i login with the new user, and IE keeps the last user until i press ctrl+F5.
The only thing i'm using for authentication is Sessions, nothing more.
Someone came acrros this issue? i've tried clear cache, clear sessions with abadon, clear, removeall and nothing seems to work when i'm on IE.
If you guys need some more info to help me with that, i'll answer as soon as possible!!
I've found the following works:
Session.Clear()
Session.Abandon()
Session.RemoveAll()
If Request.Cookies("ASP.NET_SessionId") IsNot Nothing Then
Response.Cookies("ASP.NET_SessionId").Value = ""
Response.Cookies("ASP.NET_SessionId").Expires = DateTime.Now.AddMonths(-20)
End If
Usually, browsers implement it so that ctrl+f5 means "make an http request for the current url, without the browser cache). So, no matter what you do after the fact in your server-side code, because IE is by default reloading the current page from its local memory without even hitting your server, you will not appear logged out. Then, when it does eventually go back to your server, it's still sending the same cookie because the page that would have logged you out is never actually hit.
One way to test if this is happening, is to set a breakpoint in your logout code. Refresh the page without holding ctrl in IE, and see if the breakpoint is even hit. If it's not, then you know client-side caching is the cause.
Workarounds:
This code on the server will send the page with metadata indicating the browser is not allowed, under any circumstances, to cache the page on their side:
response.Cache.SetAllowResponseInBrowserHistory(false);
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.Cache.SetNoStore();
response.Cache.SetExpires(DateTime.Now);
response.Cache.SetValidUntilExpires(true);
-- or --
When you go to your logout page with a link like this: /logout or /home?logout=1 add an extra paramter like this: /logout?cacheBust=123yt74y5t, making the last part random. This works because most browser caches will cache based on url, so if you randomly mess up an unimportant part of the url, you can get around it. One advantage to this method is that you actually want the browser to cache some pages, but not others, and this is a more client-side way of determining if you want a fresh copy from the server or not.

C# - If user refreshes page after inserting a record, a duplicate record is created. How can I prevent this?

This is true with any other functionality present on the page. I don't want the last event that happened before post back to happen again.
I believe you should take a look at the PRG Pattern (Post/Redirect/Get)
Post/Redirect/Get (PRG) is a common design pattern for web developers
to help avoid certain duplicate form submissions and allow user agents
to behave more intuitively with bookmarks and the refresh button
In ASP.NET:
POST - Submit button click causes HTTP POST
REDIRECT + GET - HttpResponse.Redirect()
MSDN, Redirecting Users to Another Page
In server code, you can programmatically redirect by calling the
Redirect method. The method sends a command to the user's browser that
causes the browser to issue an HTTP GET command for the target page.
Few important notes regarding PRG pattern:
!!! The PRG pattern cannot address every scenario of duplicate form
submission. Some known duplicate form submissions that PRG cannot
solve are:
if a web user goes back to the web form and resubmits it.
if a web user clicks a submission button multiple times before the server response loads (may be prevented by using JavaScript to disable
the button after the first click).
if a web user refreshes before the initial submission has completed because of server lag, resulting in a duplicate HTTP POST request in
certain user agents.
if a malicious web user submits the form twice despite client-side safeguards and typical browser behavior.
You should learn about the PRG (Post/Redirect/Get) pattern:
Post/Redirect/Get (PRG) is a common design pattern for web developers
to help avoid certain duplicate form submissions and allow user agents
to behave more intuitively with bookmarks and the refresh button.
Source: http://en.wikipedia.org/wiki/Post/Redirect/Get
Basically you'll want to redirect via a GET request after the user has done a POST.
you can check already exist condition before inserting record in Database.
like in stored procedure you can check
if not exists (select id from table where column name ='test' )
begin
inser statement..
end
This is about PRG. The simple way to avoid this is redirect user to same page again:
Page: Update.aspx
void btnUpdate_click(object sender, EventArgs e){
// do your update here
Response.Redirect("Update.aspx");
}
This will create a redirect-header in Resoinse and browser will create a GET request to Update.aspx page. And if the User refresh the page, a GET will be sent. Look:
User submit the form : POST
Server do updates, return a redirect-header
Browser receives the response as a redirect-command : REDIRECT
Browser sends a GET request for same page to server : GET
Browser receives the response answered by a GET
If user refreshes the page: Browsers last command was GET, so will not fires a submit again
A simple way is to use javascript to disable the button when the users click it.
A way I use to avoid refreshes when high security is needed, is the use of a small "token" in session.
Let's say, we put a small 32 bit integer in our session.
The page will contain an hidden input containing our small integer token.
Each time we receive the page request, we increment that token by one, and, before doing so, we check for equality with the one received in the request.
If they match, it is not a refresh.
If they don't match, it is a refresh.
This will also block attempt to do back and next with browser buttons.
Of course at the point that token don't matches, the page should change or you'll have again the refresh problem.
It should show something like "hey, refresh back or next not allowed, press here to continue".
For increased security, you can xor that integer with a costant value dependant for example on some other value that is constant in session.

How To Disable Button Close On Browser For Web Application?

I have Application Web based ASP.Net Framework 1.0, for security i want Button Close (X) in browser(ie,firefox,opera etc.) is disable and reason anything make browser exit, user only can exit browser with my menu logoff.
Please help me
Thanks in Advance
Regards,
Yusan Susandi.
You can't do this, sorry. You'll have to implement a server-side timeout mechanism, etc. You can make it a fairly short timeout and use an ajax request behind-the-scenes to keep the session alive, but you cannot prevent the browser from closing.
And really, you don't want to rely on doing so anyway, because browsers can crash rather than close, computers can get unplugged rather than shut down properly, etc., all without your server being notified. So you have to handle the fact that people can abruptly disappear anyway.
For the normal use case, you can encourage your users to use the Logout link instead using JavaScript:
<script>
window.onbeforeunload = function() {
if (loggedIn) {
return "Please cancel and use the Logout link instead";
}
};
</script>
...which will nag them on most (but not all) browsers, but you can't make them do it.

Possible to get return url back from javascript/jquery?

I have a problem that when a user times out on my site they are still logged in. So they can still do an ajax request. If they do an ajax request on my site my asp.net mvc authorization tag will stop this.
The authorization normally then redirects the user back to the signin page if they fail authorization.
Now since this is an ajax request what seems to be happening is it send the entire page back rendered as html. So the user never gets redirect since I just got the entire page send to me as html.
However firebug says this in the console:
http://localhost:3668/Account/signIn?ReturnUrl="return" ( this is not in the actual url bar in the web browser so I can't go up there and get it. I only can seem to see it through firebug.)
So I am not sure but maybe if I could somehow grab this url from inside my errorCallback area that would be great.
Since from my testing no error code is sent back(200 OK is sent). Instead I just get parsing error(hence why errorCallback is called) but I can't assume that every time I get parsing error it means the user timed out.
I need something better. The only other option is too look at the response and look for key works and see if it is the signin page what I don't think is that great of away to do it.
You probably want to do one of two things:
Write your server code such that ajax requests return an ajax error when a session is expired. That way the javascript will expect a return code that indicates a session timeout, and you can tell the user the session expired.
If an elegant solution isn't forthcoming because of how your framework handles this stuff, just put a chunk of HTML comment in your login page like Uth7mee3 or something; then check for the existence of that string in your ajax code.
Alternative, you can also set a timer on the web page that figures out when the session is about to time out and warn the user with a little message that lets them renew their session. Once it times out, blank out the page and give them a link to login again.
How about having a script in the Loginpage
if(document.location.href != "/Account/Login")
{
document.location.href = "/Account/Login"
}
This would work if you try to render partials in an ajax request.
(Not if you expect json)
What is the status code of the response in this situation? I think you should be able to check for a 302 here. If not, the Location header would be the next best way to check for the sign-in page.
This isn't an answer to your specific question, but the way I deal with this is to have a some client-side code that understands about the session length and prompts the user to renew a session just prior to it being ready to expire if they haven't moved off the page. If the user doesn't respond to the prompt in time, it invokes the logout action of the site -- taking the user to the login page.
You can find more information on the exact implementation, including some code, on my blog: http://farm-fresh-code.blogspot.com.

Categories