简体   繁体   中英

How to redirect the page when the filterContext.Result call to action was made in ajax method?

I came with a problem that I don't know how to fix.

The context of my problem is based on need to redirect the user to Login when a session variable is lost.

What we are doing is a decoration over the controller actions that previews to execute the action, validate that session variable called ["SesionesPorUsuarios"] where different to null

Something like this:

    [HttpPost]
    [IndicadorUltimaAccionDelSistema()]
    public JsonResult ConsulteLosProductos(string elAliasDelTipoDeProducto)
    {
        //stuffs...
    }

And then like this:

    public class IndicadorUltimaAccionDelSistema : ActionFilterAttribute
{

        /stuffs...
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (HttpContext.Current.Session["SesionesPorUsuarios"] != null)
            {               
                /stuffs...
            }
            else
            {
                /stuffs...
                filterContext.Result = new RedirectToRouteResult(
                                   new RouteValueDictionary
                                   {
                                       { "action", "Login" },
                                       { "controller", "Login" }
                                   });
            }
        }
}

our Login action is:

public ActionResult Login()
    {
        return View();
    }

We got the problem, when the action is called in an ajax method like $.post()

The post method gets all the view returned by the action "Login", but it don't redirects the user to Login page, the post method gets all the html returned by the action "Login" and it treats it like a JSON object.

在此处输入图片说明

Anyone knows how we can fix this problem, or what workarround can we apply for the need

Thanks...

You will have to check if it is an ajax request and send url as json and on client side check if that param is there redirect from client side via js:

if (filterContext.HttpContext.Request.IsAjaxRequest())
 {
     filterContext.HttpContext.Response.StatusCode = 403;
     filterContext.Result = new JsonResult { Data = "LogOut"};
 }
 else
 {
    filterContext.Result = new RedirectToRouteResult(
                               new RouteValueDictionary
                               {
                                   { "action", "Login" },
                                   { "controller", "Login" }
                               });
 }

and register ajaxError event and in that check for value and redirect :

   $(document).ajaxError(function(e, xhr, opts) {

            if (xhr.status == 403 && xhr.responseText.indexOf("LogOut") != -1) {
                window.location.href = "@Url.Action("Login", "Account")";
            }

        });

Now on any ajax call if session is null user will get redirected to login action.

You can also return an object instead of string as @Shyju demonstrated in the post, i used string to keep it simple :)

You can update your action filter to check whether the request is coming from an ajax call or not. If yes, return a json response with the login url to be redirected to. You can determine whether it is ajax call or not by checking the "X-Requested-With" header in request. For ajax request's the value will be "XmlHttpRequest"

public override void OnActionExecuting(ActionExecutingContext context)
{     
    if( YourCodeToCheckWhetherUserIsAuthenticatedHere()==false)
    {  
      var url = new UrlHelper(context.Controller.ControllerContext.RequestContext)
                                                   .Action("Login", "Account");
      if (context.HttpContext.Request.IsAjaxRequest())
      {
        context.Result = new JsonResult { Data = new { LoginUrl = url} };
      }
      //to do : Non ajax request. keep your existing code
  }
}

Now in your $.post method's call back, check this data and do whatever you want.

EDIT : Based on the comment

If you have many places you are making ajax call, you can do this check in the global ajaxComplete event.

$(function(){
    $(document).ajaxComplete(function(a,xhr,c) {
        if (xhr.status === 401) {
            var d = $.parseJSON(xhr.responseText);
            //alert("login failed");  // Let's redirect
            window.location.href = d.LoginUrl;
        }
    });
});

Request.IsAjaxMethod() checks the X-Requested-With header value. If you are using angular js's $http service to make these calls, this specific header will not be available . In that case, you need to specifically add that to your calls.

var app= angular.module('yourApp', []);

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}]);

My friends, you have gave us the answers for our problem, thankyou so much.

The way we use to fix the problem was:

if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    filterContext.HttpContext.Response.StatusCode = 403;
                    filterContext.Result = new JsonResult { Data = "LogOut" };
                }
                else {
                    filterContext.Result = new RedirectToRouteResult(
                                       new RouteValueDictionary
                                       {
                                       { "action", "Login" },
                                       { "controller", "Login" }
                                       });
                }

And check it on the global js like this:

$(function () {
            $(document).ajaxComplete(function (a, xhr, c) {
                if (xhr.status == 403 && xhr.responseText.indexOf("LogOut") != -1) {
                    window.location.href = "@Url.Action("Login", "Login")";
                }
            });
        });

The problem was solved, really really thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM