How would you overcome this issue? Jquery + ajax + server timeout - c#

I am using asp.net mvc, C# and jquery. My site is uses ajax heavily. This has lead to a problem and I am not sure how to fix it (well fix it better than my current solution).
Scenario.
User logins into my site - cookie set, server has timeout of 30mins
User walks away for 30 mins
User comes back and clicks on one my ajax enabled jquery tabs
Request sent to server
Server goes nope user timed out send them back to signin page.
since it is a an ajax request the redirect gets rendered in the tab. It look ugly(an entire page rendered in a tab), user is probably extremely confused at this point.
Problem
As far as the server and ajax is concerned the ajax request is valid and success response is sent back. So I can't go check for an error as the request was successful just not the right data coming back.
Solution 1
User logins into site.
Jquery ajax request made to find out users timeout
timeout is 60 seconds less than server timeout
Once timeout on javascript side is hit. Jquery dialog box comes up and tell them their session expired and forces them to be redirect to sign in pack.
A user can't click on anything as the dialog box blocks that. If some users firebug or something they can remove it but then server timeout will still be effect and they will get the ugly version(don't care then).
If a user makes an ajax request the timeout on the server side is reset as well as the one on the client side.
Problems
User could walk away and another person could come and the timeout message could be up but they still could have a potential of 45 seconds of trying to make a new request and reset the timeout. This is very low and not too worried about it.
Sometimes I have observed is it just times out( the client side) and I don't know why. I never can recreate the problem( seems to happen to other people but not when I am testing). So I am guessing something did not hit write or something else went wrong.
So number 2 is really the big reason why I would want to find another solution.
Solution 2 (speculation).
I was thinking maybe if I can make my own response header or something so if the server times out then I can send some 303 redirect or something in that nature that I could check for then do a jquery redirect based on that.
However I am not sure where to do that in my C# code or if I can do something like that.

You could always add a custom HTTP header in your LogOn action which could be intercepted by AJAX calls and act accordingly:
public ActionResult LogOn()
{
Response.AddHeader("X-LOGON", "LogOn");
return View();
}
And in the success callback check for the presence of this header:
$.ajax({
url: '/home/someaction',
success: function (data, textStatus, XMLHttpRequest) {
if (XMLHttpRequest.getResponseHeader('X-LOGON') === 'LogOn') {
// the LogOn page is being displayed
// probably timeout or unaithorized => act accordingly
}
}
});

I don't see why your authentication handler (action filter) can't handle this by returning 403 (forbidden) which AJAX handler will then process by setting window.location to /login.

I basically do solution 1, except that (1) I've encapsulated it into a plugin and (2) I inject the session timeout in the page when it renders. You can see details on my blog, http://farm-fresh-code.blogspot.com, in this article. One addition is that, when the client-side times out, it automatically invokes the logout action to actually terminate the session.

Related

How to empty ASP.net postback cache?

I just read What is a postback?
I have an asp.net webform on which I click a button to fill server side C# variables. If I am correct this occurs by an HTTP POST (a postback since I resend the user supplied data with the webform back to the server using the body of the HTTP request)
When the server recieves the postback, it will send some instructions bac to the client (for instance "display an alert message").
My problem here is that when I refresh (F5) the webform, what ever action that was performed last is reexecuted. Hence, a postback is reexecuted when I refresh the page, thus triggering a response from the server.
How can I disable this behavior ? By this I mean that how could hitting F5 just reload the page as if it was the first time (I guess all my code behind variables will be restoredto default too...)
This is default browser behavior. F5 will always trigger a repost if the form was submitted (PostBack).
You can get around this behavior by redirecting to the same page again after a PostBack
Response.Redirect(Request.RawUrl, false);
But if you use this, you cannot get a response to the client like you normally would. Only setting a Session before the redirect and then deal with it on the page after redirect would be the only way to get a response from the server to the client.
Better is making sure a repost will not create any problems, like duplicate database entries etc.

C# .Net MVC and CA/Siteminder middleware

History: I have a tiny app that has lived on a linux web server for a while: html5/javascript/perl cgi scripts. There is a sort of third party middle ware called Siteminder from CA that provides SSO services and it works fine. In my case on the linux box there is a dir in the DOCROOT that holds the Public facing html, js & perl cgi scripts. There is a different dir where the pages and scriots for the authorized content sits. Siteminder is configured to be aware of this auth-dir and the request paths that contain that auth-dir element.
Siteminder is tied into Apache and observes the request stream and when it sees a request with a path element that it cares about it holds the in-bound request; redirects the visitor to a branded auth page; deals with the auth flow and then, if authenticated, sends the original request on through. In this case the auth is tied to an AD group. Again, this works. My pages and code are totally unaware of the existence of Siteminder.
For reasons above my paygrade it has been decided to move the content from the linux box to an IIS server. Convert everything to C# .Net MVC. I am NOT a windows person but this is what is in my plate at the moment.
Our local Siteminder experts tell me that SM works exactly the same under IIS as linux. That once I convert my code that it doesn't need to be aware of SM either... yet something is not working.
In my case, due to user interaction a modal popup appears in the Public section (HomeController) that holds a small form. Clicking the submit button triggers a jQuery GET (I've also tried PUT, POST and a redirect) action to a method in the AuthController, a la:
$.get({
'url': "/Auth/AddNewData",
'contentType': "application/x-www-form-urlencoded; charset=UTF-8",
'dataType': "json",
'traditional': true,
'data': {
'thing': myThing,
'otherThing': myOtherThing
}
}).done(function(data, textStatus, jqXhr) {
console.log("it worked");
}).fail(function(jqXhr, textStatus, errorThrown) {
console.dir(jqXhr);
console.log(textStatus);
console.log(errorThrown);
});
I am aware that there are .Net ways of stating the target url, please bear with me.
What I expect to happen is that if the visitor does not have the auth session cookie that Siteminder sets then they should be redirected to the SM auth flow and once authorized have this request complete.
Instead, what happens is that:
I use the get method: it fires and I get a 302 "Object Moved" response.
if I use the post method: it fires and I get a 200 Ok response but the returned payload is a small amount of html from SM saying that if I am not redirected to my destination shortly to press the button included in the form in that html. The jQuery fail promis fires though because it is expecting a JSON result, not html.
if I use put nothing happens.
I comment out my jQuery ajax call and just use a "location" redirect then SM will put up its challenge page; I can log in; and, the triggering request will be "continued" into a loop of length 3: it calls the page and fails with a 302 that seems to send the request back to SM where it is sent back to the target address to get a 302 then back to Sm then back to the target but it generates a 404 message.
I am deep in the weeds here. Advice would be wonderful
Oh, PS: running this in debug mode on my desktop (no SM) works. Running the Release version on the IIS dev server with SM is what fails.
EDIT
More info: after some additional siteminder config I started getting CORS violation messages. I am setting CORS headers now but that changes nothing. Siteminder seems to strip the CORS headers :/
Another thing I have noticed is that if i craft the failing GET request as a javascript location.href=url + "?" + queryStringData redirect everything works. Current jquery is all but depreciating setting async to false so crafting a non-async version is more than I want to tackle at the moment.
The local siteminder folks will file a ticket soon I think.
EDIT 2
I have ended up with a hacky "fix". I can not use standard GET, POST, PUT, etc methods to interact with the MVC methods because Siteminder is in the way. I have added CORS headers and have tried JSONP, none of that works in this case.
I have to use "redirects" instead. Setting location.href = "/usr?thing=foo&bar=baz" in the javascript functions then redirecting to the url as a result of the MVC methods.
This might be a Siteminder config issue. The local Siteminder mavens have submitted a ticket.
Your question still isn't clear what the problem is with each of the bullets you listed. Is the GET behavior what you expect? A 302 is just a redirect, is it the redirect you expect?
For "POST", you are seeing the "post preservation" behavior. Its what SiteMinder does so that if your session has timed out in the middle of filling out a form, you don't lose your work. Post preservation is a configuration parameter in the "Agent Configuration Object" in SiteMinder. It sounds like your SM admins have configured the ACO differently for the IIS server than they did the Linux server.
PUT - nothing happens? You don't get any response at all, the connection just hangs?
Your last bullet, with the redirect loop, this looping typically indicates that your user is logged in (authenticated) but not authorized, which is a SiteMinder policy configuration issue (again it sounds like different policies are being applied to your IIS server than the Linux)
HTH!
-Richard

MVC Controller called again after redirecting to another view

I am building an e-commerce application using the eWay payment portal and I've run into an odd issue.
In my setup for eWay, I am giving a redirect URL for the payment gateway to use to come back to my application. This works correctly and at the end of the callback method I am using RedirectToAction to redirect to a Confirmation view.
However, after the callback method completes, it is called again. Only the second time will the redirect to my confirmation page complete properly.
Looking in Fiddler I appear to get a correct 302 response from my callback method to my confirmation view, however I get an icon that is the Session was aborted by the client, Fiddler, or the Server. Note that this still occurs when Fiddler is closed.
My callback method:
public ActionResult PurchaseCallback(string accessCode)
{
// payment processing
.....
return RedirectToAction("Confirmation");
}
public ActionResult Confirmation()
{
return View("Confirmation");
}
Fiddler trace:
Fiddler trace showing request and response headers:
Note the call to /Purchase/Purchase which redirects to the eWay portal, before the tunnel to eWay itself, before returning to Purchase/PurchaseCallback twice before finally arriving at /Purchase/Confirmation. Also note the icon on the first /PurchaseCallback call, which indicates an aborted session. However I don't know why it would be aborted.
There is no associated view for PurchaseCallback and the view for Confirmation has no JavaScript or other requests. I am using IIS Express, but I am using the RedirectToAction pattern in many other places without issue.
What would be causing my controller method to be called twice, and how can I stop it happening?
Check if you have the "Redirect after payment processing" option enabled in you eWAY Shared Page settings (doco here). Sometimes this can create a call to the redirect page before/just after you've clicked on the button, which would create two calls (this is particularly a problem if the delay is set to 5 seconds).

Call a method on browser closing

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.

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