MVC AJAX请求返回不正确的状态代码

问题描述 投票:1回答:1

我提交了一个标准的$.ajax()请求,如下所示:

$.ajax({
    type: "GET",
    url: myUrl
    success: function(data) {
        $("#replace").html(data)
    },
    error: function (data) {
        console.warn(data);
    }
});

或者通过将处理程序附加到ajax promise回调来执行相同的操作:

$.ajax({
    type: "GET",
    url: myUrl
})
.done(function(data, status) {
    console.log(data);
})
.fail(function(data, status) {
    console.warn(status);
});

在这两种情况下,或者在使用$.ajaxError() handler时,如果返回HTTP状态错误,则会调用错误/失败函数。


在我的ASP.NET MVC项目中,我正在尝试返回正确的HTTP状态代码,这两者都是出于语义原因并被正确的客户端处理程序捕获。

尝试#1 - 正如this answer所建议的,我试图像这样返回一个HttpStatusCodeResult

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    if (filterContext.HttpContext.Request.IsAjaxRequest())
    {
        filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized, accessResult.AccessDeniedMessage);
        filterContext.HttpContext.Response.End();
    }
    else
    {
       base.HandleUnauthorizedRequest(filterContext);
    }
}

尝试#2 - 或者,正如this answer所建议的那样,我试过返回一个JsonResult并设置Response.StatusCode

filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
filterContext.Result = new JsonResult()
{
    Data = new { Error = "Unauthorized User" },
    JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.HttpContext.Response.End();

在这两种情况下,响应仍然可以恢复为200 OK

AJAX Status Code Screenshot

Questions:

  • 我是否正确使用未授权状态代码返回AJAX响应的语义?
  • 还有其他地方可以设置我需要做的这个值吗?
  • 是否有一些服务器级别设置允许返回非200状态代码?

关于Always success on ajax post with HttpResponseMessage 401的这个问题似乎遇到了同样的错误,但是没有提出服务器端解决方案,只是允许OK错误状态代码并抓取响应来确定是否发生了错误。

javascript c# ajax asp.net-mvc http-status-codes
1个回答
1
投票

令人讨厌的问题确实与Always success on ajax post with HttpResponseMessage 401相同。响应已成功返回,但被重定向到表单登录

X-Responded-JSON: {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}}

虽然这个问题似乎没有建议服务器端解决方案,而只是依赖于解析客户端上的错误状态。 Brock Allen建议在Using cookie authentication middleware with Web API and 401 response codes的帖子中修改服务器端:

通常在使用cookie身份验证中间件时,当服务器(MVC或WebForms)发出401时,响应将转换为302重定向到登录页面(由CookieAuthenticationOptions上的LoginPath配置)。但是当进行Ajax调用并且响应是401时,将302重定向返回到登录页面是没有意义的。相反,你只是期望返回401响应。不幸的是,这不是我们使用cookie中间件获得的行为 - 响应更改为200状态代码,其中包含带有消息的JSON响应正文:

{"Message":"Authorization has been denied for this request."}

我不确定这项功能的要求是什么。要更改它,您必须通过在cookie身份验证中间件上配置CookieAuthenticationProvider,在有401未经授权的响应时接管对行为的控制:

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);
         }
     }
   }
});

请注意它处理OnApplyRedirect事件。当调用不是Ajax调用时,我们重定向。否则,我们什么都不做,允许401返回给调用者。

只需从katana项目中的helper复制IsAjaxRequest的检查:

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"));
}
© www.soinside.com 2019 - 2024. All rights reserved.