I always get statusCode=200
on ajax post at client side, while servers answers with HttpStatusCode.Unauthorized
.
My controller code:
public class AccountApiController : ApiController
{
public HttpResponseMessage Login(HttpRequestMessage request, [FromBody]LoginViewModel loginModel)
{
return request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized login.");
}
}
My ajax code:
$.ajax({
url: '/api/accountapi/login',
type: 'POST',
data: data
})
.done(function (object, status, xhr) {
alert("Success: " + xhr.status + " : " + xhr.statusText);
})
.always(function (object) {
$("#output").text(JSON.stringify(object, null, 4));
});
Result: alert with text Success: 200 : OK
and output window with:
{
"Message": "Unauthorized login."
}
So, I can get text error message, but i need to get HttpStatusCode to handle error statements. Help me, please.
More information about this issue and elegant solution from Brock Allen: http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
It might be that your page is redirecting to a login page by the forms authentication module as soon as you return HttpStatusCode.Unauthorized
.
From MSDN:
All unauthenticated users are denied access to any page in your application. If an unauthenticated user tries to access a page, the forms authentication module redirects the user to the logon page specified by the loginUrl attribute of the forms element.
The login page, or whatever page it's being redirected to, is then served with status code 200.
To elaborate on Valin's comment, and inline Brock Allen's solution.
The clue lies in the returned OK response which internally traps the redirect to a form login:
X-Responded-JSON: {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}}
If you'd like to fix on the server, instead of scraping the response for this internal error state, you can use the solution from Brock Allen's article on Using cookie authentication middleware with Web API and 401 response codes:
Normally when using cookie authentication middleware, when the server (MVC or WebForms) issues a 401, then the response is converted to a 302 redirect to the login page (as configured by the LoginPath on the CookieAuthenticationOptions). But when an Ajax call is made and the response is a 401, it would not make sense to return a 302 redirect to the login page. Instead you’d just expect the 401 response to be returned. Unfortunately this is not the behavior we get with the cookie middleware — the response is changed to a 200 status code with a JSON response body with a message:
{"Message":"Authorization has been denied for this request."}
I’m not sure what the requirement was for this feature. To alter it, you must take over control of the behavior when there is a 401 unauthorized response by configuring a CookieAuthenticationProvider on the cookie authentication middleware:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { OnApplyRedirect = ctx => { if (!IsAjaxRequest(ctx.Request)) { ctx.Response.Redirect(ctx.RedirectUri); } } } });
Notice it handles the OnApplyRedirect event. When the call is not an Ajax call, we redirect. Otherwise, we do nothing which allows the 401 to be returned to the caller.
The check for IsAjaxRequest is simply copied from a helper in the katana project:
private static bool IsAjaxRequest(IOwinRequest request) { IReadableStringCollection query = request.Query; if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest")) { return true; } IHeaderDictionary headers = request.Headers; return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest")); }
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