MVC 3 / Jquery AJAX / Session Expires / C# - 在 ajax 调用期间处理会话超时
Posted
技术标签:
【中文标题】MVC 3 / Jquery AJAX / Session Expires / C# - 在 ajax 调用期间处理会话超时【英文标题】:MVC 3 / Jquery AJAX / Session Expires / C# - Handling session timeout durng ajax call 【发布时间】:2012-05-22 08:45:25 【问题描述】:我有一个对 MVC 的 ajax 调用,它返回一个局部视图。这一切都很好,直到会话结束或 cookie 过期。当我进行 ajax 调用时,它会在一个用于局部视图的 div 中显示内容。如何在 ajax 调用期间检测到我的会话已过期并正确重定向到全屏/页面
【问题讨论】:
我也遇到了同样的问题,你找到解决办法了吗? 【参考方案1】:我建议将您的所有请求封装到一个包装器元素中:
public class JsonResponse<T>
public JsonResponse()
public JsonResponse(T Data)
this.Data = Data;
public T Data get; set;
public bool IsValid get; set;
public string RedirectTo get; set;
您要发送给客户的模型在 Data 中。
为了填充 RedirectTo,我在 Global.Asax 中使用了 GlobalAuthorize 属性并添加了 handle for HandleUnauthorizedRequests。
public sealed class GlobalAuthorize : AuthorizeAttribute
protected override void HandleUnauthorizedRequest
(AuthorizationContext filterContext)
if (filterContext.HttpContext.Request.IsAjaxRequest())
filterContext.Result = new JsonResult
Data = new JsonResponse<bool>
IsValid = false,
//RedirectTo = FormsAuthentication.LoginUrl
RedirectTo = "/"
,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
;
else
base.HandleUnauthorizedRequest(filterContext);
此外,我已将 所有 Ajax 请求封装到一个检查RedirectTo
的函数中。
function global_getJsonResult(Controller, View, data, successCallback, completeCallback, methodType)
if (IsString(Controller)
&& IsString(View)
&& !IsUndefinedOrNull(data))
var ajaxData;
var ajaxType;
if (typeof (data) == "string")
ajaxData = data;
ajaxType = "application/x-www-form-urlencoded"
else
ajaxData = JSON.stringify(data);
ajaxType = "application/json; charset=utf-8";
var method = 'POST';
if (!IsUndefinedOrNull(methodType))
method = methodType;
var jqXHR = $.ajax(
url: '/' + Controller + '/' + View,
data: ajaxData,
type: method,
contentType: ajaxType,
success: function(jsonResult)
if (!IsUndefinedOrNull(jsonResult)
&& jsonResult.hasOwnProperty("RedirectTo")
&& !IsUndefinedOrNull(jsonResult.RedirectTo)
&& jsonResult.RedirectTo.length > 0)
$.fn.notify('error', 'Login Expired', 'You have been inactive for a prolonged period of time, and have been logged out of the system.');
window.setTimeout(function() window.location = jsonResult.RedirectTo , 5000);
else if (IsFunction(successCallback))
successCallback(jsonResult, Controller + '/' + View);
,
error: function(jqXHR, textStatus, errorThrown)
if (errorThrown != 'abort')
$.fn.notify('error', 'AJAX Connection Error', textStatus + ': ' + errorThrown);
,
complete: function(jqXHR, textStatus)
if (IsFunction(completeCallback))
completeCallback(jqXHR, textStatus, Controller + '/' + View);
);
return jqXHR;
【讨论】:
我尝试使用你的方式,我的 HandleUnauthorizedRequest 完美运行,但它从来没有出现在 global_getJsonResult() 方法中,你能给我一个你如何封装你的 jquery 方法的例子吗? 不确定你的意思。上面的例子有一个封装ajax请求的方法,在我的JS代码中所有的请求都使用这个方法。【参考方案2】:您可以使用 javascript 在客户端上创建一个计时器,该计时器将在会话超时时向用户显示一个对话框。您只需将计时器的值设置为会话超时。然后在 ajax 请求时,它也会重置倒计时。
var g_sessionTimer = null;
function uiSessionInit()
id = "uiTimeout";
timeout = 3600000 * 24; // 1 day timeout
uiSessionSchedulePrompt(id, timeout);
$('body').ajaxStart(function ()
// reset timer on ajax request
uiSessionSchedulePrompt(id, timeout);
);
function uiSessionSchedulePrompt(id, timeout)
if (g_sessionTimer)
clearTimeout(g_sessionTimer);
g_sessionTimer = setTimeout(function () uiSessionExpiring(id); , timeout);
function uiSessionExpiring(id)
// create a dialog div and use this to show to the user
var dialog = $('<div id="uiTimeout"></div>').text("Your session with has timed out. Please login again.");
$('body').append(dialog);
$('#uiTimeout').dialog(
autoOpen: true,
modal: true,
title: 'Expired Session',
buttons:
"OK": function()
$(this).dialog('close');
,
close: uiSessionDialogClose
);
function uiSessionDialogClose()
// take user to sign in location
location = 'http://www.mypage.com';
【讨论】:
【参考方案3】:已经 8 年了,但我刚刚遇到了一个类似的问题,即在用户的身份验证 cookie 过期后进行的将部分视图加载到模式中的 Ajax 调用会导致完整的登录页面被加载到模式中.我就是这样解决的。
首先,我在我的登录页面上添加了一个隐藏控件。 value
不是严格要求的,但我认为它使标记更具可读性:
<input id="isLoginPage" type="hidden" value="true" />
然后我像这样修改了 Ajax 调用。我正在使用 jQuery,但同样的原理也适用于普通的旧 Javascript:
$.ajax(
url: `/mypartialview`,
type: "GET",
success: function (data)
var $modal = $("#myModal");
$modal.find(".modal-content").html(data);
if ($modal.find("#isLoginPage").length > 0)
window.location.replace("/");
$modal.modal("show");
);
这是基于如果用户的身份验证已过期,MVC 的默认行为是返回登录页面,所以我“嗅探”Ajax 调用返回的视图以获取 isLoginPage
隐藏输入,如果找到,我知道登录页面已经返回,所以我只是将用户重定向到应用程序的根目录,然后 MVC 将重定向到主登录页面。
如果您的应用程序的根目录允许匿名访问,您可以将 window.location.replace("/")
替换为应用程序登录页面的路径,例如window.location.replace("/account/login")
.
通过这项工作,我将解决方案封装在一个函数中以简化事情并避免重复自己:
function handleAjaxData($container, data)
$container.html(data);
if ($container.find("#isLoginPage").length > 0)
window.location.replace("/");
然后我可以像这样在我的 Ajax 调用中使用它:
$.ajax(
url: `/mypartialview`,
type: "GET",
success: function (data)
var $modal = $("#myModal");
handleAjaxData($modal.find(".modal-content"), data);
$modal.modal("show");
);
您显然可以更进一步,将 Ajax 调用本身包含在函数中,但在我的情况下,这会涉及一些复杂的回调,所以我没有打扰。
【讨论】:
以上是关于MVC 3 / Jquery AJAX / Session Expires / C# - 在 ajax 调用期间处理会话超时的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET MVC 3 - Ajax.BeginForm 与 jQuery 表单插件
使用 WIF 和 jquery ajax 请求时 ASP.NET MVC 3 中的会话 Cookie 过期处理