MVC AJAX请求

时间:2018-03-01 16:16:54

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

我提交了这样的标准$.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

问题:

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

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

1 个答案:

答案 0 :(得分: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"));
}