Logging out from an ajax call - asp.net-mvc-3

Nowadays we tend to split the amount of work made in just one page before this one renders, to speed things up, so, we normally load the basic and then upon DOM is ready, we call all parts to bring more data showing the normal animated loading gif ...
What is the normal procedure to, when requesting for such method, the user session already expired and he/she needs to login again?
Currently I have no such thing and the browser only shows endless the loading gif... I was wonder what would be the best approach to such trivial problem.
I thought about sending an error flag that, from javascript I could read and redirect to the login page
$.get( url, data, function(data) {
if(data.logout) document.location.href = '/LogOut';
...
});
but I get nothing from my controller soon the session expired...
P.S. My web application is made using ASP.NET MVC 3.

I would recommend you start with the following article in which Phil Haack explains how to properly handle 401 errors in ASP.NET MVC without automatically redirecting you to the LogOn page.
Then simply do your AJAX requests as normal:
$.get(url, data, function(data) {
// if we got here it means that the request succeeded
// => do whatever you have to do for this case
});
and then you could register a global AJAX event to handle the 401 case for all AJAX requests:
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
if (jqXHR.status == 401) {
// the server returned 401 (Unauthorized) =>
// redirect to the LogOn page
window.location.href = 'put your logon url here';
}
});

Related

In ie11 ajax call -window.location redirect not working, extjs

I am facing an issue with redirecting to another domain, from ajax call success in ie. It shows issue only in ie, in chrome and firebox it works well. I am using extjs for ajax call and in response i want to redirect to another domain based on the success value.
But if i place an javascript alert in the ajax success it works in ie.
If we place the same redirection code outside success of ajax call it works.
Ext.Ajax.request({
url: 'API/LogOut.ashx',
scope: this,
success: function (response) {
var result = response.result.data;
if (result['LogOutUrl'])
{
window.location.assign(result['LogOutUrl']);
I even tried to redirect like this window.location.assign('/tax.aspx'). But even this is not working. Anybody has any clue on that.
I also faced same issue for IE browser, in IE due to security it blocks window redirection like window.open().It results in popup blocker.
Try using delayed task or setTimeout() after your ajax response comes.
Ext.Ajax.request({
url: 'API/LogOut.ashx',
scope: this,
success: function (response) {
var result = response.result.data;
if (result['LogOutUrl'])
{
setTimeout(function(){
window.location.assign(result['LogOutUrl']);
},1000);
...
Post your result here.If possible give some fiddle link.

This page isn't redirecting properly error with MVC3 + AJAX + Forms Authentication

EDIT: Removed non-relevant code/desc, since the issue was not just to do with the initial code there.
I have an MVC3 based application that uses a lot of Ajax calls (such as with jqGrid) and Forms Authentication. I also use the [Authorize] attribute on certain controller/actions that I call with Ajax in most cases. Every so often my application falls over with a 'This page isn't redirecting properly' or a 'this page has a redirect loop'.
I checked this out with fiddler. After logging in as a user and trying to access pages that require authentication, sometimes I get redirected to Account/LogOn which then goes into an infinite loop. This usually happens when I'm calling any controller/action with an Authorize attribute with an Ajax call. The application seems to send out a 302 redirect to Account/Logon. The Account/Logon call then seems to redirect to itself. And the textView on Fiddler shows the following.
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
I have the following in my Global.asax file
protected void Application_EndRequest()
{
var context = new HttpContextWrapper(this.Context);
//if we are an ajax request and forms authentication caused a 302, then we actually need to do a 401
if (System.Web.Security.FormsAuthentication.IsEnabled && context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
{
context.Response.Clear();
context.Response.StatusCode = 401;
}
}
And this in my main Layout page
<script type="text/javascript">
$(document).ajaxError(function (xhr, props) {
if (props.status == 401) {
location.reload();
}
});
</script>
My web.config setting for Forms authentication has this
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880"/>
</authentication>
The redirect starts every so often and it is not with the same controller/action either. Just seems quite random. I am not sure if the cookie is expiry for the user and causing this issue for some reason or if it is an issue with the application pool recycling. Any suggestions on how to get around this would be most appreciated. Been struggling with this the last few days now, so any help from the experts will be great. Thank You
decorate your action method with Authorize attribute to make it available to authenticated/logged in users, after that check user role.
I don't see a loop in the above code. But maybe in one of controller1 or controller2 you have a redirect back to this home/index action.
I would suggest to run fiddler while testing the site, when a redirect loop happens you can easily detect it there, and then it is easier to find out what's wrong with the code.
Please see the answer in the linked question. This was the resolution to my redirect loop problem. Thank you for all your inputs.
IIS Session timeout and Forms Authentication loop

Extend/Override jquery.ajax.done function to detect .net logon screen

I'm using forms authentication on an asp.net MVC application and I'm using jquery and ajax to create a rich user interface. Some users tend to leave the page open for hours and their login session is expiring as expected. If the user click a link or reloads the page the login screen is returned as expected. If they click a button or trigger an ajax call the ajax call is returning the login html instead of the expected html or JASON result. Resulting in a mangled page with half a login screen.
As I've already coded a lot of ajax calls I thought I could extend or override the default .done event to add a check for the login screen before continuing with whatever event I've programmed.
For example i have this function :
function CallAjax() {
$.ajax({type: "GET", url: "foo" })
.done(function (data) { $('#result').val(data); });
}
is it possible to override the default implementation of .done so do a check without rewriting this function? My check would probably to see if the result is a html response if so search for "login" to see if its the login page.
I would recommend you to extend the ASP.NET Forms Authentication module as Phil Haack explained in this blog post so that it no longer redirects to the login page when requested with AJAX but returns a 401 HTTP status code instead. Then you could simply use the .fail callback and intercept the 401 status code. The .done handler will not be invoked in this case.
I tried Darin's suggestion but after hours of trying I just couldn't get it to work in my set up. However I stumbled across this rather simpler solution which worked for me first time:
just add this to the global.asax
protected void Application_EndRequest()
{
var context = new HttpContextWrapper(this.Context);
if (FormsAuthentication.IsEnabled &&
context.Response.StatusCode == 302 &&
context.Request.IsAjaxRequest())
{
context.Response.Clear();
context.Response.StatusCode = 401;
}
}
}
Taken from http://jvance.com/blog/2012/09/21/FixFormsAuthentication302.xhtml

Cross Domain issue(Working in IE not in other browser)

I am fetching data from a URL using an AJAX call. It is giving a json object to me.
When I run the application, the page is working fine in IE with a conformation that
the page is accessing information that is not under its control.
This poses a security risk. Do you want to continue?
But that is not working in other browsers like Firefox, Chrome, Safari, etc.
i don't know what is the problem. Please explain to me why it is occurring and how to solve the issue?
My Code:
<!DOCTYPE html>
<html>
<head>
<title>Search Engine</title>
<script src="JS/jquery-1.4.2.min.js"></script>
<script>
$(document).ready(function () {
$.support.cors = true;
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src", "http://192.168.13.111:7090/?uname=bhagirathip&wt=json&fl=*,score");
script.setAttribute("type", "text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
});
function Search() {
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
}
</script>
</head>
<body>
<form id="form">
<div style="text-align: center">
<input type="search" id="searchInput" autofocus />
<input type="button" id="btnSearch" onclick="Search()" value="Search" />
</div>
</form>
</body>
</html>
You can't make cross-domain AJAX calls across domains. This is a security feature in web browsers to prevent malicious JavaScript code from scraping rendered data in a web page and then shipping it off to some rogue website on some other domain.
By restricting AJAX requests to same domain, browser vendors ensure that JavaScript imported from other sources cannot send data to any server other than the server the HTML page was served from.
In Internet Explorer, it's prompting you, but any smart user who encounters such a message is likely to say no. Presenting your users with such warning messages is not a good design practice and does not inspire confidence in the legitimacy of your application.
The only way that you can send data across domains is to use a browser hack technique called "script tag remoting", which essentially involves using HTML elements that aren't restricted by the same domain policy. For instance script tags can make HTTP GET requests to any server:
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src","http://192.168.9.11/userInput/?key="+userInput);
script.setAttribute("type","text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
Using this method, you can send data to a remote server. Note that, to get JSON data back, you must wrap it, or pad it, in a JavaScript function and define a callback in the JavaScript code to handle the response:
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
And your server-side code must return content text/javascript, calling the handler, and passing your JSON as an argument:
callbackJsonHandler({"key":"value","key1":"value2"});
When the browser downloads the JavaScript to the browser, the JavaScript runs immediately, giving you a hook to use to access the JSON in the response.
Since you're using jQuery, you can also check out jQuery JSONP, or JSON with Padding, which can be used to generate a JavaScript response so that you can handle callbacks from these requests to the remote server. Note that the server must be setup to handle JSONP requests for this to work properly, similar to the above setup.
Another solution to the issue of making cross-domain requests from a browser whose HTML document is served from exampleA.com to a server whose domain is exampleB.com is to use a proxy.
Let's assume that the HTML document you're working with is served from exampleA.com. You own exampleA.com, and you can access the server side and client side code. exampleB.com, on the other hand, is a remote server owned or controlled by someone else. exampleB.com has some data you want to use in exampleA.com.
We know that AJAX won't work, because of the same origin policy, which is in place to protect rogue apps from doing bad things with people's data. However, servers aren't restricted to same domain policy. This means that your app can do the following:
||exampleA.com/test.html|| ---> http req --> ||exampleA.com/getData|| --http req --> ||exampleB.com/getJSON||
Server-side: (As in your server, exampleA.com):
In other words, on your server that you're using to serve the HTML, you write some code that makes an HTTP request from your server to the third-party server:
// JSON URL which should be requested
$json_url = 'http://www.exampleB.com/getJSON';
// Initializing curl
$ch = curl_init( $json_url );
// Configuring curl options
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json')
);
// Setting curl options
curl_setopt_array( $ch, $options );
// Getting results
$result = curl_exec($ch); // Getting JSON result string
See Getting JSON Data with PHP Curl for more details. Each server-side platform has the ability to make HTTP connections to servers.
// now, send the data in the response
HttpResponse::status(200);
HttpResponse::setContentType('application/json');
HttpResponse::setData($result);
HttpResponse::send();
See PHP HTTPResponse. Again, whatever language you're working with should have the ability to return data from a string.
Put the above code in a file called "getJSON.php", assuming you're using PHP. Make sure there is no whitespace between the opening <?php and the beginning of the document; otherwise, you will not be able to set the headers. There is likely a better way to send this response, but since your platform isn't specified, I'll leave that as an exercise for the reader.
Client-side code:
var searchURL = "/getJSON.php"; //From this URL json formatted data is present.
$.ajax({
url: searchURL,
type: 'GET',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
try {
alert(data);
}
catch (err) {
alert(err);
}
}
});
Now, in the above JavaScript code, you make a same-domain AJAX request to your server exampleA.com, and then your server makes a request on your behalf to exampleB.com to get the data, then exampleA.com returns the data in the response to the browser.

Redirecting browser using AJAX

Is there a way to redirect a user to a page (login page in my case) when an AJAX query is made by the user to a server? The server is supposed to serve data only if the session is set or else the user should be redirected. I have tried sending a header("location:...") request but the browser handled it as a string (xmlhttp.response) rather than acting on it.
Not directly. Your callback function would have to handle it.
For example, if the server sends the text "LOGIN;/login.php;" then your onreadystatechange call back could have the snippet
if (xmlhttp.responseText.substring(0,6) == 'LOGIN;') {
window.location.href = xmlhttp.responseText.split(";")[1];
return;
}
If you're using a framework for the Ajax, this code could be in whichever callback gets the result of the Ajax call.
No. Not directly. You can return something special which should be handled as a redirect. But since the browser isn't looking to navigate and it won't.
In the callback function you can set the window.location to the new page if the session is not set.

Resources