Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

442
Views
Handling session timeout in ajax calls

I'm making an ajax call using jquery to an asp.net mvc controller action:

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult GetWeek(string startDay)
        {
            var daysOfWeek = CompanyUtility.GetWeek(User.Company.Id, startDay);
            return Json(daysOfWeek);
        }

When session times out, this call will fail, as the User object is stored in session. I created a custom authorize attribute in order to check if session was lost and redirect to the login page. This works fine for page requests, however it doesn't work for ajax requests, as you can't redirect from an ajax request:

[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;
        }
    }

I read on another thread that when the user isn't authenticated and you make an ajax request, you should set the status code to 401 (unauthorized) and then check for that in js and redirect them to the login page. However, I can't get this working:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))
            {
                filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }

Basically, it'll set it to 401, but then it'll continue into the controller action and throw an object ref not set to an instance of an object error, which then returns error 500 back to the client-side js. If I change my custom Authorize attribute to validate ajax requests as well and return false for those that aren't authenticated, that makes the ajax request return my login page, which obviously doesn't work.

How do I get this working?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You could write a custom [Authorize] attribute which would return JSON instead of throwing a 401 exception in case of unauthorized access which would allow client scripts to handle the scenario gracefully:

[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);
        }
    }
}

then decorate your controller/actions with it and on the client:

$.get('@Url.Action("SomeAction")', function (result) {
    if (result.message) {
        alert(result.message);
    } else {
        // do whatever you were doing before with the results
    }
});
over 4 years ago · Santiago Trujillo Report

0

I wouldn't change JsonRequestBehavior to AllowGet. Instead I suggest:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        OnAuthorizationHelp(filterContext);
    }

    internal void OnAuthorizationHelp(AuthorizationContext filterContext)
    {

        if (filterContext.Result is HttpUnauthorizedResult)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.End();
            }
        }
    }
}

and add global js ajax errors handler:

   $(document).ajaxError(function (xhr, props) {
        if (props.status === 401) {
            location.reload(); 
        }
   }
over 4 years ago · Santiago Trujillo Report

0

Even though this is well past answered, I think this is the shortest and sweetest answer if you are using .NET 4.5. Little property called SuppressFormsAuthenticationRedirect which was added. Set to true and it will not perform the 302 Redirect to login page.

http://msdn.microsoft.com/en-us/library/system.web.httpresponse.suppressformsauthenticationredirect.aspx

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // returns a 401 already
        base.HandleUnauthorizedRequest(filterContext);
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            // we simply have to tell mvc not to redirect to login page
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
        }
    }
}

Assuming you plan on handling the ajax requests fail/error callback, in which you will get a 401 Unauthorized.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!