Таймаут сеанса при вызове ajax

Я знаю, что это дубликат, но я не мог получить надежное решение (для веб-сайта asp.net).

Я просто хочу перенаправить на страницу входа в систему, если сеанс истекает. Я пробовал следующее:

1. с использованием кода состояния jquery

    $.ajax({
     type: "POST",
     url: "stream.asmx/SomeMethod",
     contentType: "application/json; charset=utf-8",
     dataType: "json",
     success: function (msg) {
        //success msg
     },
     error: function (request, status, error) {
        if (status = 403) {
            location.href = 'login.aspx';
        }
     }
    });

Проблема: возвращает тот же код статуса (403) для других ошибок, который я ожидаю только для таймаута сеанса.

2. Отправка сообщения json о том, закончился ли сеанс

код позади:

    if (!object.Equals(HttpContext.Current.Session["User"], null))
    {
        Id = int.Parse(HttpContext.Current.Session["User"].ToString());
    }
    else
    {
        result = from row in dtscrab.AsEnumerable()
                 select new
                 {
                     redirectUrl = "login.aspx",
                     isRedirect = true
                 };
    }

для успеха $.ajax:

    success: function (msg) {
        if (msg.d[0].isRedirect) {
            window.location.href = msg.d[0].redirectUrl;
        }
        else {
            //load containt
        }
     }

Проблема:. Он почему-то не вызывает строку успеха ajax, если сеанс истекает (он возвращает правильный json). И даже это неверно, если у меня много запросов ajax на странице (нужно обрабатывать глобально).

Однако я видел этот пост, который действительно хорош, но для mvc используется AuthorizeAttribute: handling-session-timeout-in-ajax-calls

Итак, я могу использовать ту же концепцию, которая используется в mvc, используя AuthorizeAttribute в asp.net web api? Если нет, то как я могу устранить проблему, с которой я столкнулся (какой-либо из вышеупомянутых двух)?

Ответ 1

Наконец, я закончил.

public class IsAuthorizedAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                var sessions = filterContext.HttpContext.Session;
                if (sessions["User"] != null)
                {
                    return;
                }
                else
                {
                    filterContext.Result = new JsonResult
                    {
                        Data = new
                        {
                            status = "401"
                        },
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet
                    };

                    //xhr status code 401 to redirect
                    filterContext.HttpContext.Response.StatusCode = 401;

                    return;
                }
            }

            var session = filterContext.HttpContext.Session;
            if (session["User"] != null)
                return;

            //Redirect to login page.
            var redirectTarget = new RouteValueDictionary { { "action", "LogOn" }, { "controller", "Account" } };
            filterContext.Result = new RedirectToRouteResult(redirectTarget);
        }
    }

Обработка клиентской стороны

<script type="text/javascript">
    $(document).ajaxComplete(
       function (event, xhr, settings) {
           if (xhr.status == 401) {
               window.location.href = "/Account/LogOn";
           }
    });
</script>

Ответ 2

Код статуса 403 приведет к тому, что jQuery вызовет метод отказа. Сохраните тот же код из второй попытки, но переместите обработчик перенаправления на метод отказа вместо метода успеха. В методе успеха относитесь к нему так, как обычно.

Ответ 3

Проблема:

У меня была такая же проблема в моем приложении Razor MVC, бросая исключения, в то время как ajax-вызовы, сделанные при истечении времени ожидания сеанса.

То, как мне удалось решить эту проблему, - это контролировать каждый запрос ajax с помощью простого легкого метода действий (RAZOR MVC), возвращающего переменную bool, независимо от того, прошел ли запрос или нет. Пожалуйста, найдите код ниже.

Макет/Мастер-страница/ Script файл:

<script>
var AuthenticationUrl = '/Home/GetRequestAuthentication';
var RedirectUrl = '/Account/Logon';

function SetAuthenticationURL(url) {
AuthenticationUrl = url;
}

function RedirectToLoginPage() {
window.location = RedirectUrl; 
}

 $(document).ajaxStart(function () {
 $.ajax({
    url: AuthenticationUrl,
    type: "GET",
    success: function (result) {
        if (result == false) {
            alert("Your Session has expired.Please wait while redirecting you to login page.");
            setTimeout('RedirectToLoginPage()', 1000);
        }
    },
    error: function (data) { debugger; }
});

})

Затем на стороне Home Controller/Server вам нужен метод проверки запроса и возврата булевой переменной.

    public ActionResult GetAuthentication ( )
    {
        return Json(Request.IsAuthenticated, JsonRequestBehavior.AllowGet);
    }

Это подтвердит каждый запрос ajax, и если срок действия сеанса истек для любого запроса ajax, он будет предупреждать пользователя с сообщением и перенаправлять пользователя на страницу входа.

Я также предлагаю не использовать стандартное предупреждение для предупреждения. Пользователь какой-то тип подсказки для форматированных предупреждений div. Стандартные оповещения JS могут заставить пользователя нажать OK перед перенаправлением.

Надеюсь, это поможет..:)

Спасибо, Riyaz

Ответ 4

вы можете установить время ожидания сеанса, чтобы сообщить о чем-то вроде....

<script type="text/javascript"> 

//get a hold of the timers
var iddleTimeoutWarning = null;
var iddleTimeout = null;

//this function will automatically be called by ASP.NET AJAX when page is loaded and partial postbacks complete
function pageLoad() { 

    //clear out any old timers from previous postbacks
    if (iddleTimeoutWarning != null)
        clearTimeout(iddleTimeoutWarning);
    if (iddleTimeout != null)
        clearTimeout(iddleTimeout);
    //read time from web.config
    var millisecTimeOutWarning = <%= int.Parse(System.Configuration.ConfigurationManager.AppSettings["SessionTimeoutWarning"]) * 60 * 1000 %>;
    var millisecTimeOut = <%= int.Parse(System.Configuration.ConfigurationManager.AppSettings["SessionTimeout"]) * 60 * 1000 %>; 

    //set a timeout to display warning if user has been inactive
    iddleTimeoutWarning = setTimeout("DisplayIddleWarning()", millisecTimeOutWarning);
    iddleTimeout = setTimeout("TimeoutPage()", millisecTimeOut);
} 

function DisplayIddleWarning() {
    alert("Your session is about to expire due to inactivity.");
} 

function TimeoutPage() {
    //refresh page for this sample, we could redirect to another page that has code to clear out session variables
    location.reload();
} 

Ответ 5

4xx - это коды состояния ошибок HTTP, и это приведет к тому, что jquery выполнит обратный вызов onFailure.

Кроме того, остерегайтесь использовать 3xx для перенаправления, когда вы хотите обработать полезную нагрузку. Internet Explorer, по моему опыту, просто перенаправляет (не глядя на полезную нагрузку), когда возвращается код состояния 3xx.

Я бы сказал, бросьте 403 и обработайте ситуацию. Для клиента 403 подразумевается, что доступ к ресурсам запрещен. Могут быть несколько причин, и это нормально.