• .net自定义错误页面实现升级篇


      问题描述:

      在上一篇博文 “.net自定义错误页面实现” 中已经介绍了在.net中如何实现自定义错误页面实现(有需要者可以去上一篇博文了解),单纯按照上一篇博文那样设置,能够实现所有请求的异常自定义跳转,但是这样又会产生一个问题:当通过ajax提交请求获取接口提交请求,如果出现未处理的异常也会被重定向到自定义错误页面。

      针对ajax请求或者接口请求,这样返回一个重定向页面,用户体验显然不是太友好,针对这个问题,下面简单总结一下我自己的想法和解决方案,当然不一定科学和合理,所以也希望有大牛多多指点。

      解决思路,我想到的有二:
    解决方案一:
      从物理结构上分割,将web项目严格分割成两个项目(当然可根据需要继续细分):网站(只有网站页面资源等内容)、接口(包括网站的所有数据逻辑处理,页面的数据请求交互都是直接同接口交互(js技术)),
      只是网站项目按照上一篇博文方式设置自定义错误页面方式,这样是能够解决问题,项目也会更加的清晰,也有很多公司的项目就是按照这种方式(尤其是webApp),
      但是在实际项目中,很多项目是没有达到这种严格区分的,所以下面的解决方案二,将介绍一个更通用的方式

    解决方法二:

      解决思路是:将上一篇博文 .net自定义错误页面实现 与 上上一篇博文 .net捕捉全局未处理异常的3种方式 结合使用,并在实际开发中严格约定(出了url地址请求以外的其他请求都通过post请求实现交互),在扑捉到异常时,如果是post请求,处理异常,并清除异常。具体以步骤如下:
      第一步:定义一个请求处理结果数据MODEL,代码如下:
      

        /// <summary>
        /// 请求结果MRequestResult
        /// </summary>
        public class MRequestResult
        {
            /// <summary>
            /// 请求结果编码(是一个枚举值)
            /// </summary>
            private RequestResultCodeEnum requestResultCode;
    
            /// <summary>
            /// 处理结果具体的返回值
            /// </summary>
            private object resultValue;
    
            /// <summary>
            /// 请求结果编码(是一个枚举值)
            /// </summary>
            public RequestResultCodeEnum RequestResultCode
            {
                get
                {
                    return this.requestResultCode;
                }
    
                set
                {
                    this.requestResultCode = value;
                }
            }
    
            /// <summary>
            /// 处理结果具体的返回值
            /// </summary>
            public object ResultValue
            {
                get
                {
                    return this.resultValue;
                }
    
                set
                {
                    this.resultValue = value;
                }
            }
        }
    
    
        /// <summary>
        /// 请求结果编码枚举值()
        /// </summary>
        public enum RequestResultCodeEnum
        {
            /// <summary>
            ///  请求成功
            /// </summary>
            Success = 1,
    
            /// <summary>
            /// 请求失败
            /// </summary>
            Fail = -1,
        }

    第二步:按照 上一篇博文: .net自定义错误页面实现的步骤,配置好自定义错误页面相关配置操作

    第三步:按照 上上一篇博文:.net捕捉全局未处理异常的3种方式 的步骤实现全局异常为处理相关操作设置

    第四步:在扑捉全局未处理的异常中,添加上针对post请求的异常处理过滤(直接输入封装后的),具体代码如下:

      /// <summary>
            /// 异常处理
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void context_Error(object sender, EventArgs e)
            {
                //此处处理异常
                HttpContext ctx = HttpContext.Current;
                HttpResponse response = ctx.Response;
                HttpRequest request = ctx.Request;
    
                //获取到HttpUnhandledException异常,这个异常包含一个实际出现的异常
                Exception ex = ctx.Server.GetLastError();
                //实际发生的异常
                Exception iex = ex.InnerException;
    
                //// 异常日志落地
                //// 异常日志落地包括:记录异常文本文件日志、或者记录异常日志数据库等等(根据实际项目需要做记录)
    
                //// 获取请求方法
                string httpMethod = request.HttpMethod;
                //// 如果是POST请求,那么是以下请求之一
                //// ajax接口请求
                //// form表单提交
                //// 这种情况的异常,不用跳转至自已的异常错误页面,直接返回对应系统异常
                if (httpMethod.ToUpper() == "POST")
                {
                    //// 构建返回对象值
                    MRequestResult requestResultM = new MRequestResult();
                    requestResultM.RequestResultCode = RequestResultCodeEnum.Fail;
                    requestResultM.ResultValue = "系统异常,请联系管理员!";
    
                    response.Write(JsonConvert.SerializeObject(requestResultM, Formatting.Indented));
                    ctx.Server.ClearError();//处理完及时清理异常
                }
            }

    代码实例:

    ajax请求方法及其逻辑处理实例代码:

        $(function () {
            $.ajax({
                async: true,
                type: "post",
                url: "../ActionTestResult/ContentResultTest",
                data: "name=xu",
                success: function (resultValue) {
    
                    if (resultValue) {
                        //// 解析处理结果
                        var resultObj = $.parseJSON(resultValue);
    
                        //// 当RequestResultCode==1 说明该请求成功
                        ////(备注:并不代表处理成功,具体是否处理成功需要通过ResultValue的值根据接口约定解析做相应的逻辑处理)
                        if (resultObj["RequestResultCode"] == 1) {
                            //// 自定义请求成功逻辑处理
                            //// 通过解析具体的ResultValue的值做相应的逻辑处理.....
                            if (resultObj["ResultValue"]) {
                                var doResult = resultObj["ResultValue"].split('^');
                                if (doResult && doResult.length > 1) {
                                    if (doResult[0] == 1) {
                                        //// 说明处理成功,做相应的逻辑处理
                                        alert("处理成功!");
                                    } else {
                                        //// 处理失败
                                        alert(doResult[1]);
                                    }
    
                                } else {
                                    alert("操作失败!");
                                }
    
                            } else {
                                alert("未知结果");
                            }
    
                        } else {
                            //// 说明请求异常
                            //// 自定义逻辑处理
                            alert(resultObj["ResultValue"]);
                        }
                    } else {
                        //// 自定义逻辑处理
                        alert("操作失败!");
                    }
    
                    console.log(resultValue);
                },
                error: function (data) {
                    //// 自定义逻辑处理
                    alert("系统异常,请联系管理员。电话:8888888");
                    console.log(data);
                }
            });
        });

    ajax对应的后台请求接受实例代码:

            /// <summary>
            /// 测试
            /// </summary>
            /// <returns></returns>
            public ContentResult ContentResultTest(string name)
            {
                //// 构建请求处理结果Model
                MRequestResult requestResultM = new MRequestResult() { RequestResultCode = RequestResultCodeEnum.Success };
    
                //// 业务处理结果
                string doResult = string.Empty;
    
                //// 本次自作简单的参数非空判断,只一个示例
                //// 处理结果本例中也只是通过^链接表示,在实际处理过程中,可以将结果通过一个Json字符串
                if (string.IsNullOrEmpty(name))
                {
                    doResult = "-1^操作失败:名称不能为空!";
                }
                else
                {
                    ///// 其他自定义业务逻辑处理,此处省略.....
                    doResult = "1^操作成功";
                }
    
                requestResultM.ResultValue = doResult;
    
                //// 返回结果
                return Content(JsonConvert.SerializeObject(requestResultM, Formatting.Indented));
    
            }

    是不是觉得说的有点绕,本人表述能力有限,不懂的评论交流。
    最后:个人能力有限也许该解决方式并不友好,有更好的解决方法,也欢迎留言交流,多多指点,多多指教

  • 相关阅读:
    二叉树的四种遍历方法笔记
    SpringBoot简单连接数据库以及查询数据
    在Mac下配置Maven环境
    二叉树的存储结构
    二叉树区分左右
    JDBC编程流程以及详细代码
    树的存储结构
    Java基础总结
    Linux命令简写和全称
    spring-security使用
  • 原文地址:https://www.cnblogs.com/xiaoXuZhi/p/customErrors_httpErrorsUp.html
Copyright © 2020-2023  润新知