Handling session time out when ajax call to C# mvc controller not working
Asked Answered
M

2

7

When calling a function from ajax. Program flow does not recognized the expired session i.e not redirect to the login page. Instead of that, it saves the record. I am working in c# .net mvc. So how can i handle session while ajax call. Here i gave my codes.

 $.ajax({ 
            type: "POST",
            url:'/Employee/SaveEmployee',
            data:
            {
                Location:$("#txtLocation").val(), 
                dateApplied:$("#txtDateApplied").val(), 
                Status:$("#ddStatus").val(), 
                mailCheck:$("#ddMailCheck").val(),
                ...
                ...
                ... 
            },
            success: function (result) 
            {

            },
            error: function (msg) 
            {
            }
      });

Here the controller

[Authorize]
public string SaveEmployee(string Location, string dateApplied, string Status, string mailCheck, ...)
{
      objEmpMain.FirstName = firstName;
      objEmpMain.LastName = lastName;
      objEmpMain.Initial = Initial;
      objEmpMain.Address1 = Address;
      ...
      ... 
      ...
} 
Mouflon answered 3/10, 2012 at 7:38 Comment(0)
S
24

The result of your AJAX call will still likely end up appearing successful (although, don't worry, it won't actually execute your action method), and invoke your success handler. This is because you are expecting HTML, and that is what you are receiving (albeit, the resulting HTML is likely your login page, and not the HTML you wanted). As an aside, if you expected JSON (using dataType:'JSON'), it would trigger an error, because it would be parsing HTML as JSON.

What you need to do is prevent FormsAuth from redirecting the login page for AJAX requests. Now, AuthorizeAttribute faithfully returns a NotAuthorizedResult, which sends an HTTP 401 Not Authorized response to the client, which is ideal for your AJAX client.

The problem is that FormsAuth module checks the StatusCode and if it is 401, it performs the redirect. I've combatted this issue in this way:

1) Create my own derivative type of AuthorizeAttribute that places a flag inHttpContext.Items to let me know authorization failed, and I should force a 401 rather than a redirect:

public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    /// <summary>
    /// Processes HTTP requests that fail authorization.
    /// </summary>
    /// <param name="filterContext">Encapsulates the information for using <see cref="T:System.Web.Mvc.AuthorizeAttribute"/>. The <paramref name="filterContext"/> object contains the controller, HTTP context, request context, action result, and route data.</param>
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest()) filterContext.HttpContext.Items["AjaxPermissionDenied"] = true;

        base.HandleUnauthorizedRequest(filterContext);
    }
}

2) Add to your Global.asax.cs:

    protected void Application_EndRequest(Object sender, EventArgs e)
    {
        if (Context.Items["AjaxPermissionDenied"] is bool)
        {
            Context.Response.StatusCode = 401;
            Context.Response.End();
        }
     }

3) Add a statusCode handler to your jQuery AJAX setup:

$.ajaxSetup({
    statusCode: {
        401: function() {
            window.location.href = "path/to/login";
        }
    }
});

4) Change the controllers or actions where you want this behavior from using AuthorizeAttribute to AjaxAuthorizeAttribute:

[AjaxAuthorize]
public string SaveEmployee(string Location, string dateApplied, string Status, string mailCheck, ...)
{
      objEmpMain.FirstName = firstName;
      objEmpMain.LastName = lastName;
      objEmpMain.Initial = Initial;
      objEmpMain.Address1 = Address;
      ...
      ... 
      ...
} 
Soursop answered 3/10, 2012 at 8:5 Comment(8)
Actually my present class looks like following "public class EmployeeController : Controller". Are you instruct me to change like following "public class AjaxAuthorizeAttribute : AuthorizeAttribute" ????Mouflon
Just swap out AuthorizeAttribute for AjaxAuthorizeAttribute that you decorated on your controllers or controller actions. See #4 which I just added.Soursop
Sorry, can you explain me where i need to create the "public class AjaxAuthorizeAttribute : AuthorizeAttribute" class???Mouflon
And for your information already i handled the session time out. But it works for the function call from view. But only the ajax call is the major problem.Mouflon
You would create it anywhere in your MVC project, or in any project in your solution that the MVC application references. For example, you could place it right in the root of the MVC project.Soursop
Your instructed codes working well.. but the redirection alone is the problem for me. Where i can write ajax setup function?Mouflon
Dude.. i tested the "HttpContext.Response.StatusCode.ToString();" it gives us 200 as result. :(Mouflon
@HackedByChinese - your solution works great. Just a follow-up question - why do you call Context.Response.End() in Application_EndRequest?Counteraccusation
S
1

I would like to sugguest you to use StatusCode = 306. I met some problem when use 401.IIS treat 401 different from what I understand. 306 works fine for me.

Regards.

Supination answered 5/6, 2013 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.