【问题标题】:Handling session time-outs in Datatables (with server-side datasource processing)处理数据表中的会话超时(使用服务器端数据源处理)
【发布时间】:2011-10-05 09:09:20
【问题描述】:

我有一个由服务器端 Ajax 数据源支持的数据表表单(它在后端使用 struts 操作来处理请求、获取数据并发送 JSON 响应)。 服务器端操作需要在认证模式下运行,即需要有一个活动会话。

在数据表中处理会话超时错误的最佳方法是什么?目前它只是显示一个 JSON 格式错误,这不是用户的最佳选择。出于明显的原因(兼容性、未来可维护性等),我不想去更改数据表代码。有没有一种处理错误的简洁方法?

我一直在考虑在 JSON 响应中嵌入错误消息,但是在前端流中拦截它的最佳位置是哪里?

编辑:我认为进行此类后期处理的最佳位置是在 fnServerData 中,对吗?

【问题讨论】:

  • 没错;只需定义一个error 回调。

标签: javascript jquery struts datatables struts-1


【解决方案1】:

我会返回一个包含某种错误代码的 JSON 响应。要处理它,您需要按照您的推测定义 fnServerData。但是,出于这个原因,我会在使用错误回调之前强烈考虑用例:

错误只是获取资源的任何问题,并使用状态代码。假设会话在服务器上终止。用户请求数据,服务器发回 500 错误。错误回调说:“好吧,这太糟糕了。让我们重定向到登录页面。”一切都很好。

但是……用户提出了请求。无论出于何种原因(大型数据集、网络条件),该请求都需要一点时间。同时,用户决定导航到另一个页面,中断呼叫响应循环。没有响应,错误回调被触发,用户被重定向到登录页面(或错误回调中设置的任何函数)。

问题是我不知道任何状态代码(不过我很想知道!我不介意在这里犯错!)用于捕获和处理“会话已过期”。

我并不是说您“不应该”或“不能”使用错误回调。但是该函数必须考虑会话到期以外的错误。您可能需要根据状态代码进行不同的处理。如果您的函数能够优雅地处理所有这些情况,那就太好了!在一个应用程序中,我们确实重定向到登录页面,并且错误回调通常会由于误报而跳闸,从而将用户错误地转储到登录页面。对于“会话过期”的情况,我们通过 JSON 消息在成功回调中捕获它。

[在 Dave 出色的 cmets 之后更新:] 如果您的服务器返回一个有用的服务器错误(401、403、550 或在您的场景中有意义的任何内容),那么在 .ajax() 调用中使用带有 statusCode 参数的 fnServerData(即一口!)也可以。我认为这是相同的工作量:通过您已经编写的方法返回 JSON,或者通过您应该已经可以访问的方法返回状态错误。选择对您有意义的一项。

【讨论】:

  • 刚刚在 .ajax 中发现了 statusCode 参数,这可能有助于解决这方面的问题。对于过期的会话,我仍然会使用成功处理程序,对其他问题使用 statusCode 或错误。
  • 如果用户离开页面,Ajax 请求就会消失,并且不会触发回调,不是吗?服务器是否发回成功或错误的 HTTP 代码是偏好和域的问题。需要会话但没有会话的 IMO 请求应返回“禁止”代码,因为这是事实。
  • 你会想的。我不确定涉及什么魔法,但如果您在请求中间导航离开,回调确实会触发。不过,禁止代码是个好主意。使用 statusCode 参数处理它也很容易。如果您的应用程序不需要区分会话到期和其他禁止状态,我倾向于将其作为更好的解决方案。
  • 我的错,我按照stackoverflow.com/questions/1906023/…使用beforeUnloads,很久没有真正考虑过;现在我觉得很傻:)
  • 谢谢先生们,这就是我最终做的事情:当服务器端会话超时时返回一个格式良好的 JSON,其中包含错误消息,并在客户端的 fnServeData 上解析它
【解决方案2】:

以下技术对我有用......我知道现在回复为时已晚,但希望代码能帮助某人

1) 检查控制器(MVC)中的会话是否超时并返回 应该在客户端处理的状态码

if (!Request.IsAuthenticated)
{
    return new HttpStatusCodeResult((HttpStatusCode)302, "Authentication timeout");
}

2) 在客户端使用 jQuery 全局 ajax 错误,它会捕获所有 ajax 调用的错误。检查状态码并重定向到您的登录页面

$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
   if (jqxhr.status === 302) {
      document.location.href = '/account/login';
   }
});

3) [可选] 禁用数据表中的警告并在控制台中检查错误

/*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】:

    尽管这个问题已经很久没有提出来了,但如果有人需要,我还是会发布我的解决方案。

    此解决方案适用于 1.10.16 版的 JQuery 数据表。

    经过一番挖掘,我找到了在会话到期时显示警报的功能。这里是:

    /**
         * 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 );
            }
        }
    

    如您所见,对类型变量进行检查以查看它是否为函数。如果是,它会被调用。注意类型变量是这样获取的:

    var type = ext.sErrMode || ext.errMode;
    

    所以我这样做了:

    //Check the message and redirect
      $.fn.dataTable.ext.errMode = function (settings, tn, msg) {
        if (msg.indexOf("YourErrorCode") != -1) {
          window.location = "/login";
        }
      }
    

    只需将 YourErrorCode 替换为您需要的内容即可。 我承认这不是最干净的代码,但它确实有效。

    【讨论】:

      【解决方案4】:

      我在这里使用比尔马蒂诺的答案完成了它: 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)
              }
      
           });
      }
      

      在 Ajax 源响应中,您应该返回一个 Json 字符串,如下所示:

      {"error": "expired"}
      

      【讨论】:

        【解决方案5】:

        1.在获取 ajax 错误页面中使用此代码。或者还使用了页脚文件。重定向到登录页面后,此代码在会话超时时工作,没有出现 ajax 错误。

        $(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.单击调用函数时出错的按钮..将一行放在函数中

         $.fn.dataTable.ext.errMode = 'none';
        

        举个例子

        function ChangeUrl(){
                $.fn.dataTable.ext.errMode = 'none';
                product_table.fnStandingRedraw();
            }
        

        【讨论】:

          猜你喜欢
          • 2014-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多