Asp.net-Mvc
處理 ajax 呼叫中的會話超時
我正在使用 jquery 對 asp.net mvc 控制器操作進行 ajax 呼叫:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult GetWeek(string startDay) { var daysOfWeek = CompanyUtility.GetWeek(User.Company.Id, startDay); return Json(daysOfWeek); }當會話超時時,此呼叫將失敗,因為使用者對象儲存在會話中。我創建了一個自定義授權屬性,以檢查會話是否失去並重定向到登錄頁面。這適用於頁面請求,但不適用於 ajax 請求,因為您無法從 ajax 請求重定向:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AuthorizeUserAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { if (!httpContext.Request.IsAjaxRequest()) {//validate http request. if (!httpContext.Request.IsAuthenticated || httpContext.Session["User"] == null) { FormsAuthentication.SignOut(); httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString()); return false; } } return true; } }我在另一個執行緒上讀到,當使用者未通過身份驗證並且您發出 ajax 請求時,您應該將狀態程式碼設置為 401(未經授權),然後在 js 中檢查它並將它們重定向到登錄頁面。但是,我無法正常工作:
protected override void OnActionExecuting(ActionExecutingContext filterContext) { if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null)) { filterContext.RequestContext.HttpContext.Response.StatusCode = 401; } else { base.OnActionExecuting(filterContext); } }基本上,它會將其設置為 401,但隨後它將繼續進入控制器操作並拋出未設置為對象錯誤實例的對象引用,然後將錯誤 500 返回給客戶端 js。如果我更改我的自定義 Authorize 屬性以驗證 ajax 請求並為那些未通過身份驗證的請求返回 false,這會使 ajax 請求返回我的登錄頁面,這顯然不起作用。
我如何讓這個工作?
您可以編寫一個自定義
[Authorize]屬性,該屬性將返回 JSON 而不是在未經授權的訪問情況下引發 401 異常,這將允許客戶端腳本優雅地處理場景:[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class MyAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult { Data = new { // put whatever data you want which will be sent // to the client message = "sorry, but you were logged out" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { base.HandleUnauthorizedRequest(filterContext); } } }然後用它和客戶端裝飾你的控制器/動作:
$.get('@Url.Action("SomeAction")', function (result) { if (result.message) { alert(result.message); } else { // do whatever you were doing before with the results } });