代码之家  ›  专栏  ›  技术社区  ›  musefan

在ajax请求期间自定义异常处理会导致httpexception

  •  0
  • musefan  · 技术社区  · 6 年前

    当我的应用程序遇到类型为的异常时 UnauthorizedAccessException 在ajax请求期间,我希望自己处理行为并返回自定义json响应。

    所以我推翻了 OnException 方法,我的所有控制器都继承自该方法,如下所示:

    protected override void OnException(ExceptionContext filterContext)
    {
        var exception = filterContext.Exception;
    
        if (exception is UnauthorizedAccessException)
        {
            filterContext.ExceptionHandled = true;
    
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                filterContext.HttpContext.Response.ContentType = "application/json";
    
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                string json = serializer.Serialize(new { IsUnauthenticated = true });
                filterContext.HttpContext.Response.Write(json);
    
                filterContext.HttpContext.Response.End();
            }
            else
            {
                filterContext.Result = RedirectToAction("LogOut", "Account");
            }
        }
        else
        {
            // Allow the exception to be processed as normal.
            base.OnException(filterContext);
        }
    }
    

    现在这基本上就是我想要的。如果在ajax请求期间发生异常,我的javascript将根据需要获得正确的json对象。

    但是,问题是应用程序随后会遭受 HttpException 内部消息:

    发送HTTP头后无法重定向。

    以及异常的堆栈跟踪:

    在system.web.httpresponse.redirect(字符串url,布尔endresponse,布尔永久) 在system.web.security.formsauthenticationmodule.onleave(对象源,eventargs eventargs) 在system.web.httpapplication.syncEventExecutionStep.system.web.httpapplication.ieExecutionStep.Execute() 在system.web.httpapplication.executestepimpl(iexecutionstep步骤) 在system.web.httpapplication.executestep(iexecutionstep步骤,boolean&同步完成)

    在将断点添加到 Application_Error 方法 MvcApplication 这样地:

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();
        LogError(ex);
    }
    

    因此,尽管我的应用程序正按照用户体验的要求生成结果。我有一个“幕后”的例外,我真的不想发生。

    这里出什么事了?我能做些什么来防止异常发生呢?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Adrian    6 年前

    继续从评论,我认为这是最好的张贴作为一个答案,由于字符限制。这在一定程度上是一个答案,因为我面前没有一个合适的项目可以测试。

    当我在评论中说我不能复制时,那是因为我在webapi2项目中运行了那些测试,我不会有相同的行为。

    如果我没记错的话,你的问题在于你在mvc项目中实现了类似api的功能,当然你看到的是预期的行为。

    当您获得UnauthorizedException时,框架将尝试自动重定向到登录屏幕(或错误页面)。你必须(显然)禁止这种行为。

    您可以尝试使用以下命令在处理程序中抑制它:

    filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
    filterContext.HttpContext.Response.Redirect(null);
    

    最终结果应该大致如下:

    if (!filterContext.HttpContext.Request.IsAjaxRequest())
    {
        filterContext.HttpContext.Response.StatusCode = 
        (int)System.Net.HttpStatusCode.Unauthorized;
    
        filterContext.HttpContext.Response.ContentType = "application/json";
    
    
    
        filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
    
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string json = serializer.Serialize(new { IsUnauthenticated = true });
        filterContext.HttpContext.Response.Write(json);
    
        filterContext.HttpContext.Response.End();
    }
    

    如果这不起作用;您的身份验证中间件也可能负责设置此重定向,而这将不幸地设置在其他地方。

        2
  •  0
  •   Adrian    6 年前

    我的另一个答案是错误的,我刚刚测试过。

    这个问题的解决办法和我以前给你的解决办法略有不同。您的中间件是导致问题的原因。

    我怀疑你在使用我正在使用的;microsoft.aspnet.identity。

    在startup.cs中,需要添加一个applyredirect委托。

    你的代码应该和我的相似:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login"),
                    Provider = new CookieAuthenticationProvider
                    {
                        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                            validateInterval: TimeSpan.FromMinutes(30),
                            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
                         OnApplyRedirect = ctx =>
                         {
                             // add json response here...
                             ctx.RedirectUri = null;
    
                         }
                    }
                });
    

    从原始处理程序中,移动响应并将其添加到ctx.response…

    希望这能让它重回正轨。在onapplyredirect中,您可能需要检查它是否是ajax请求,然后禁用重定向,否则您将得到难看的asp默认错误页。:-)