更改 ajax 请求的 response.statuscode 会引发错误“发送 HTTP 标头后服务器无法设置状态”
Posted
技术标签:
【中文标题】更改 ajax 请求的 response.statuscode 会引发错误“发送 HTTP 标头后服务器无法设置状态”【英文标题】:Changing response.statuscode for ajax requests raise error "Server cannot set status after HTTP headers have been sent" 【发布时间】:2015-06-13 08:58:50 【问题描述】:我在一个 MVC 项目中工作,其中每个操作方法的用户角色和权限都存储在数据库中。我想要实现的是通过覆盖 AuthorizeAttribute 来使用 mvc 中的授权过滤器功能。这样我就可以全局注册我的自定义授权过滤器。
这是我正在尝试做的事情,遵循this method。我正在关注this article 来处理ajax 请求。
protected override bool AuthorizeCore(HttpContextBase httpContext)
//Custom permission checking logic
return false;//no permission for all methods-Just for testing
public override void OnAuthorization(AuthorizationContext filterContext)
base.OnAuthorization(filterContext);
CheckIfUserIsAuthenticated(filterContext);
private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
// If Result is null, we’re OK: the user is authenticated and authorized.
if (filterContext.Result == null)
return;
var httpContext = filterContext.HttpContext;
var request = httpContext.Request;
var response = httpContext.Response;
var user = httpContext.User;
// If here, you’re getting an HTTP 401 status code. In particular,
// filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here.
if (request.IsAjaxRequest())
if (user.Identity.IsAuthenticated == false)
response.StatusCode = (int)HttpStatusCode.Unauthorized;//401
else
response.StatusCode = (int)HttpStatusCode.Forbidden;//403
response.SuppressFormsAuthenticationRedirect = true;
response.End();// This line is causing the problems
return;
if (user.Identity.IsAuthenticated)
//Redirect to customerror page
问题是当我使用 ajax post 调用方法时,我的自定义异常过滤器捕捉到错误提示 "Server cannot set status after HTTP headers have been sent "
如果我删除 response.End(),我会在 ajax 错误处理程序方法中得到 401 响应,而不是 403。
我试过了
HttpContext.Current.ApplicationInstance.CompleteRequest()
而不是 response.end,但我也收到 401 错误
有没有办法避免这个异常?
更新 我在 javascript 中使用这个通用错误处理程序方法来捕获所有 ajax 请求错误(我需要正确的状态码来响应):
function ajaxFailed(xhr, textstatus, errorthrown)
debugger;
if (textstatus == "error")
if (xhr.status == 401)
window.location = "/Account/Login";
if (xhr.status == 403)
$("#divoutput").html("you don't have permission.");
if (xhr.status == 500)
$("#divoutput").append("<br/> internal servererror." + xhr.responseText);
更新 2: 我目前的解决方案: 在我的自定义异常处理程序过滤器中检查引发异常的 Exception.Message 属性,如果消息是:“服务器无法在发送 HTTP 标头后设置状态”,则忽略它。
我知道这是一种低效的方法,但我还没有其他解决方案。等待一个好的解决方案:)
【问题讨论】:
【参考方案1】:尝试改变处理请求的顺序:
public override void OnAuthorization(AuthorizationContext filterContext)
CheckIfUserIsAuthenticated(filterContext);
base.OnAuthorization(filterContext);
更新:
你链接的文章说你必须处理其他事件处理方法 HandleUnauthorizedRequest
:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
不像你那样OnAuthorization
。
更新 #2: 尝试使用缓冲输出
Response.BufferOutput = true;
因此您的服务器被阻止将标头发送回客户端。
【讨论】:
if (filterContext.Result == null) 如果我这样做总是正确的。 那是因为没有执行验证 - 但没有发送标头。 我不明白你。我需要先执行 base.OnAuthorization(filterContext) 以便正确设置 user.Identity.IsAuthenticated 属性。然后在我的自定义方法中,我正在检查这个值以查找它是身份验证问题还是授权问题。 此方法将headers
发送回客户端。之后,您将无法更改响应的状态。
@Sharun 更新了答案。以上是关于更改 ajax 请求的 response.statuscode 会引发错误“发送 HTTP 标头后服务器无法设置状态”的主要内容,如果未能解决你的问题,请参考以下文章
如果中间发生页面更改,AJAX 请求/响应的数据会发生啥情况