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.