On our MVC website, we secure our endpoints with the Authorize attribute, however I would like to redirect the user to the login screen when this occurs. My first solution was to redirect on Application_EndRequest in Global.asax.cs:
protected void Application_EndRequest(object sender, EventArgs e)
{
if (Response.StatusCode == (int) HttpStatusCode.Unauthorized)
{
Response.ClearContent();
Response.Redirect("/Account/Login");
}
}
The problem with this is that some of our views are loaded by AJAX, in which case we do not want to show the login screen within dynamically-loaded div (this happens for example when the back button is pressed after logging out). It would be better if the request still returned the login screen, but with a 401 Unauthorized status code so that we can detect this event. Obviously this will not work with this approach because the redirection relies on a 302 status code.
Instead, I would rather 'insert' the login screen content inside Application_EndRequest with a 401 status code. So, instead of the Response.Redirect, I tried this:
...
Response.ClearContent();
Server.TransferRequest("~/Account/Login");
Response.StatusCode = (int) HttpStatusCode.Unauthorized;
...
The redirect works nicely, but because this performs a new request, I can't set the status code in this way, and I get a 200. Still no good for detecting an unauthorized request.
I also tried:
...
Response.ClearContent();
Server.Transfer("~/Account/Login");
Response.StatusCode = (int) HttpStatusCode.Unauthorized;
...
But I get an exception "Error executing child request for /Account/Login."
I also tried:
...
Response.ClearContent();
HttpContext.Current.RewritePath("~/Account/Login");
Response.StatusCode = (int) HttpStatusCode.Unauthorized;
Response.End();
...
But this throws an exception "Thread was being aborted". I'm not sure if the Response.End() is necessary but without it, I just get a standard IIS 401 error.
How can I return the content of my login screen but with a 401 status code?
Sending a 401 AND a ViewObject or RedirectObject is not how the MVC Framework was designed to work: -- a few posts have cleverly shown that returning a 401 with a View witn an authorization filter..
I specify the MVC Framework, but this is not even the prefered way to use the HTTP Protocol.
View() method, a ViewResult is createdWhether a Redirect or a View eventually reaches the client browser either,
HTTP Return Code of 200 -- Success will be returnedOr
HTTP Return Code of 302 -- Redirect will be returnedThe reason for this convention is that, the server is "handling" the redirect. If the user is not authorized, the server will redirect the user to the login page.
Simlarly, in AJAX or asynchronous HTTP requests, so long as an HTML View is returned, the HTTP request is considered a success. Redirect (302) is not returned for asynchronous requests.
Sending Error Codes to client:
If you want to return a 401 unauthorized to the client, that usually means that you want to the client to "handle" the unauthorized request by navigating to the Login or Error View.
$.ajax({
url: loginURL,
data: $("#form").serialize(),
type: "POST",
dataType: "html"
})
.success(function (result, status) {
/*additional logic*/
})
.error(function (xhr, status) {
if (xhr.status == 401)
{
window.location = unauthorizedUrl; //redirect to unauthorized url
}
});
What if you want to Redirect to Login Page AND Display an Error
your question makes most sense if you want to redirect to a Login Page AND display an Error

Then, the convention is to Add your error message into Viewbag or a ModelState Error
such as:
var user = await signInManager.UserManager.FindByNameAsync(model.UserName);
ModelState.AddModelError("", "Invalid username or password.");
return View(model);
In your View, to have code that looks for an error:
A ValidationSummary would pickup the Model error
@Html.ValidationSummary(true)
This specific example of Bad Login Attempt doesn't exactly speak to your example.
I couldn't find an image for a user redirected because they were not authorized, but, in this case, the logic is similar. Error Msg can be populated with a QueryString, Viewbag, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With