Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 37880|回复: 0

想抛就抛:Application_Error中统一处理ajax请求执行中抛出的异常

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-9 12:42:38 | 显示全部楼层 |阅读模式

    女朋友不是想抛就抛,但异常却可以,不信请往下看。

    今天在MVC Controller中写代码时,纠结了一下:

    public async Task<ActionResult> Save(int? postId)
    {
        if(!IsOwner(postId.Value, userId))
        {                    
            //抛不抛异常呢?
        }
    }

    在这个地方要不要抛异常呢?

    如果不抛异常,就得这么写:

    public async Task<ActionResult> Save(int? postId)
    {
        if(!IsOwner(postId.Value, userId))
        {
            return Json(new {
                isSuccess = false,
                message = "尝试执行未经授权的操作" });
        }
    }

    而且通常在这样的情况下,还需要记录日志,于是代码变成:

    if(!IsOwner(postId.Value, userId))
    {
        Logger.Default.Info("UnauthorizedSave", "...");
        return Json(new {
            isSuccess = false,
            message = "尝试执行未经授权的操作" });
    }

    如果抛异常呢,代码就可以这么写:

    if(IsOwner(postId.Value, userId))
    {                    
        throw new UnauthorizedAccessException();
    }

    代码显得更简洁,更具表达力,而且记录错误日志可以在Application_Error中统一处理:

    protected void Application_Error(Object sender, EventArgs e)
    {
        var lastError = Server.GetLastError();
        if (lastError != null)
        {                
            Logger.Default.Error("Application_Error", lastError);               
            Response.StatusCode = 500;
            Server.ClearError();
        }
    }

    但这会带来一个问题,客户端收到的将是自定义500错误页面的html代码,不仅没有具体的错误信息,而且在ajax回调时还要额外处理,而通常我们最期待的是一个json格式的返回结果。

    于是要想实现“想抛就抛”,就必须解决:如何在Application_Error中统一处理ajax请求处理过程中产生的异常,并将之转换成json格式的响应内容返回给客户端。

    分解一下,就变成了2个问题:

    1)如何在Application_Error中判断一个请求是否是ajax请求?

    今天上午通过MVC的扩展方法IsAjaxRequest解决了,详见如何在Global.asax中判断是否是ajax请求

    if ((new HttpRequestWrapper(Request)).IsAjaxRequest())
    {
    } 

    2)如何生成json格式的响应内容并返回给客户端?

    这个可以通过Json.NET+Response.Write来解决,代码如下:

    Response.Clear();
    Response.ContentType = "application/json; charset=utf-8";
    Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(
        new { isSuccess = false, message = lastError.Message }));
    Response.Flush();

    最终实现“想抛就抛”的代码如下:

    protected void Application_Error(Object sender, EventArgs e)
    {
        var lastError = Server.GetLastError();
        if (lastError != null)
        {           
            CNBlogs.Infrastructure.Logging.Logger.Default.Error("Application_Error", lastError);
    
            if(Request != null && (new HttpRequestWrapper(Request)).IsAjaxRequest())
            {                    
                Response.Clear();
                Response.ContentType = "application/json; charset=utf-8";
                Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(
                    new { isSuccess = false, message = lastError.Message }));
                Response.Flush();
                Server.ClearError();
                return;
            }
    
            Response.StatusCode = 500;
            Server.ClearError();
        }
    }

    ajax客户端收到的结果如下:

     从此,可以尽情地抛异常了。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-7 17:11 , Processed in 0.062142 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表