【问题标题】:Incorrect Status Code returned on MVC AJAX RequestMVC AJAX 请求返回的状态码不正确
【发布时间】:2018-03-01 16:16:53
【问题描述】:

我正在提交一个标准的$.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 状态错误时调用 error/fail 函数。


在我的 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 响应的语义,我是否正确?
  • 是否还有其他地方可以设置我也需要做的这个值?
  • 是否有一些服务器级别设置允许返回非 200 状态代码?

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

【问题讨论】:

  • 不太清楚为什么这不能按预期工作,但我确实注意到在您的图片中,响应标头有一个X-Responded-JSON,它实际上包含您作为 JSON 的响应数据。也许先尝试清除响应:filterContext.HttpContext.Response.Clear();
  • @TheMuffinMan,是的 - 我也看到了 - 我认为肯定有办法将数据填充到响应中的某个位置,并能够在客户端做出适当的反应。很多人会将Success 添加到他们返回的Data 对象中,但是从语义的角度来看,当我手动指定其他内容时,请求未经授权并且仍然以200 状态返回,这仍然困扰着我
  • 在第一个示例中,您检查当前请求的类型 isajaxrequest 是否可以将代码更改为 filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized; filterContext.HttpContext.Response.End(); 并尝试?可能您没有设置响应。
  • @NavoneelTalukdar,每次尝试都添加了对Response.End() 的调用,在这两种情况下,返回状态仍然是 200

标签: javascript c# ajax asp.net-mvc http-status-codes


【解决方案1】:

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

<b>X-Responded-JSON</b>: {"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 返回给调用者。

IsAjaxRequest 的检查只是从 katana 项目中的 helper 复制而来:

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

【讨论】:

    猜你喜欢
    • 2012-04-20
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    相关资源
    最近更新 更多