Reputation: 4488
I'm trying to write an API with a login method + others. When there is an issue logging in, I would like to return a custom HTTP error code to the client with a custom response body. The problem is that on error the request is getting redirected to the home page.
[HttpPost]
[AllowAnonymous]
public JsonResult ApiLogIn(LoginModel model)
{
if (ModelState.IsValid)
{
var outcome = _authService.LogIn(model);
if (outcome == LogInOutcome.Success)
{
return Json(new { }); // Empty on success
}
else
{
Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return Json(new { reason = outcome.ToString() });
}
}
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { }); // Empty or invalid model
}
How do I stop it from getting redirected on error?
Upvotes: 0
Views: 1103
Reputation: 42497
The issue is the fact that late in the request lifecycle, the FormsAuth module checks to see if the Response.StatusCode
is 401, and if so, redirects to the login page.
You can try a different status code (like 403, granted that's not quite appropriate for your scenario). The other option is to delay setting the Response.StatusCode
to 401 until the EndRequest
event in your Global.asax.
I solved this by adding a flag into Context.Items
and checking for the presence of the flag in EndRequest
:
Global.asax.cs - Add this method
protected void Application_EndRequest(Object sender, EventArgs e)
{
if(Context.Items["AjaxPermissionDenied"] is bool) // FormsAuth module intercepts 401 response codes and does a redirect to the login page.
{
Context.Response.StatusCode = 401;
Context.Response.StatusDescription = "Permission Denied";
Context.Response.End();
return;
}
}
In your controller
[HttpPost]
[AllowAnonymous]
public JsonResult ApiLogIn(LoginModel model)
{
if (ModelState.IsValid)
{
var outcome = _authService.LogIn(model);
if (outcome == LogInOutcome.Success)
{
return Json(new { }); // Empty on success
}
else
{
Context.Items["AjaxPermissionDenied"] = true;
return Json(new { reason = outcome.ToString() });
}
}
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { }); // Empty or invalid model
}
Upvotes: 1