问题
I have a datatables form that's backed by a server-side Ajax data source (which uses a struts action in the backend to process the request, fetch the data and send a JSON response). The server-side operation needs to run in authenticated mode, i.e. there needs to be an active session.
What is the best way to handle session timeout errors in Datatables? At present it just shows a JSON formatting error, which is not the best option for the user. I do not want to go and change the datatables code for obvious reasons (compatibility, future maintainability etc). Is there a neat way of handling errors?
I was thinking along the lines of embedding error message in the JSON response but where is the best place to intercept it in the front-end flow?
EDIT: I presume the best place for doing such post processing would be in fnServerData, am I correct?
回答1:
I would fire back a JSON response containing some sort of error code. To process it, you need to define fnServerData as you have surmised. However, I would strongly consider the use case before using the error callback for this reason:
Error is simply any problem fetching the resource, and uses status codes. Let's say the session is terminated on the server. User requests the data, the server sends back a 500 error. Error callback says, "Well, that sucked. Let's redirect to a login page." Everything works great.
However... the user makes a request. The request is taking a little bit of time for whatever reason (large data set, network conditions). In the meantime, the user decides to navigate to another page, interrupting the call-response loop. With no response, the error callback is tripped and the user is redirected to a login page (or whatever function is set in the error callback).
The problem is that there's no status code that I'm aware of (I'd love to know, though! I don't mind being wrong here!) for 'session has expired' in order to capture and process.
I'm not saying you "shouldn't" or "can't" use the error callback. But the function has to take into account errors other than the session expiring. You might need to get into processing differently based on status codes. If your function handles all those cases elegantly, great! In one application, we are indeed redirecting to login page, and the error callback would often trip due to a false positive, dumping the user incorrectly to the login page. For the case of "session expired" we are catching it in the success callback via a JSON message.
[updated after Dave's excellent comments: ] If you have your server return a useful server error (401, 403, 550 or whatever makes sense in your scenario) then using fnServerData with statusCode parameter in the .ajax() call (that's a mouthful!) would work just as well. I think it's the same amount of work: return JSON via a method you've already written, or return status error via methods you should already have access to. Choose which one makes sense for you.
回答2:
Below technique worked for me ... I know it was too late to respond but hoping the code will help someone
1) Check if session is timed out in the controller (MVC) and return the status code which should be handled at the client side
if (!Request.IsAuthenticated)
{
return new HttpStatusCodeResult((HttpStatusCode)302, "Authentication timeout");
}
2) At the client side use jQuery global ajax Error, which catches the errors from all the ajax calls. Check for the status code and redirect to your login page
$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
if (jqxhr.status === 302) {
document.location.href = '/account/login';
}
});
3) [Optional] Disable the warnings from data tables and check the errors in the console
/*disable datatable warnings*/
$.fn.dataTable.ext.errMode = 'none';
/*display warnings in the console*/
$tblDashboard.on('error.dt', function (e, settings, techNote, message) {
console.log('An error has been reported by DataTables: ', message);
});
回答3:
Even though it has been a long time since this question has been asked i'm going to post my solution if just in case anybody needs it.
This solution applies to version 1.10.16 of JQuery Datatables.
After a bit of digging arround I found the function that shows the alert when the session expires. Here it is:
/**
* Log an error message
* @param {object} settings dataTables settings object
* @param {int} level log error messages, or display them to the user
* @param {string} msg error message
* @param {int} tn Technical note id to get more information about the error.
* @memberof DataTable#oApi
*/
function _fnLog( settings, level, msg, tn )
{
msg = 'DataTables warning: '+
(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
if ( tn ) {
msg += '. For more information about this error, please see '+
'http://datatables.net/tn/'+tn;
}
if ( ! level ) {
// Backwards compatibility pre 1.10
var ext = DataTable.ext;
var type = ext.sErrMode || ext.errMode;
if ( settings ) {
_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
}
if ( type == 'alert' ) {
alert( msg );
}
else if ( type == 'throw' ) {
throw new Error(msg);
}
else if ( typeof type == 'function' ) {
type( settings, tn, msg );
}
}
else if ( window.console && console.log ) {
console.log( msg );
}
}
As you can see there is a check on the type variable to see if it's a function. If it is it gets invoked. Note that the type variable is obtained like this:
var type = ext.sErrMode || ext.errMode;
So i did this:
//Check the message and redirect
$.fn.dataTable.ext.errMode = function (settings, tn, msg) {
if (msg.indexOf("YourErrorCode") != -1) {
window.location = "/login";
}
}
Just replace YourErrorCode with want you need and it will work. I'll admit it's not the cleanest code ever but it works.
回答4:
I have done it using the answer from bill martino here: http://datatables.net/forums/discussion/4377/catch-text-returned-from-server-side-ajax-call
"fnServerData": function ( sSource, aoData, fnCallback ) {
// get filter ID
var filter_id = $('#storedFilter_id').val();
// send filter ID
aoData.push(
{ "name": "filter_id", "value": $.trim(filter_id) }
);
$.getJSON( sSource, aoData, function (json) {
// check for expired session being returned, if so, send the user back to the login page
if(json.error == 'expired'){
document.location.href='index.cfm?fuseaction=login.form';
}
else{
fnCallback(json)
}
});
}
On the Ajax Source response you should return a Json string like this:
{"error": "expired"}
回答5:
1.Using this code in your getting ajax error page. or also used footer file.this code working for at session timeout after redirect to login page not getting ajax error.
$(document).ajaxError(function(event, jqxhr, settings, exception) {
if (exception == 'Unauthorized') {
// Prompt user if they'd like to be redirected to the login page
window.location = '<?=route("admin.login")?>';
}
});
function CheckSession() {
var session = '<%=Session["name"] != null%>';
//session = '<%=Session["username"]%>';
if (session == false) {
window.location = '<?=route("admin.login")?>';
}
}
setInterval(CheckSession(),500);
2.click on button called to function at time getting error..put the one line in function
$.fn.dataTable.ext.errMode = 'none';
like one example
function ChangeUrl(){
$.fn.dataTable.ext.errMode = 'none';
product_table.fnStandingRedraw();
}
来源:https://stackoverflow.com/questions/7658975/handling-session-time-outs-in-datatables-with-server-side-datasource-processing