.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)); }
是不是觉得说的有点绕,本人表述能力有限,不懂的评论交流。
最后:个人能力有限也许该解决方式并不友好,有更好的解决方法,也欢迎留言交流,多多指点,多多指教
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
- tLinux 2.2下安装Mono 4.8
- WordPress评论回复邮件样式美化教程
- 基于Aspose.Pdf把pdf文件每一页转换为图片
- 分布式文件存储的数据库开源项目MongoDB
- 使用 JavaScriptService 在.NET Core 里实现DES加密算法
- 拒绝全英文垃圾评论!仅用代码实现
- 在.NET Core 里使用 BouncyCastle 的DES加密算法
- 微信小程序:为了满足三方需求,我们一直在改变
- 让陌生人能够相互自由交易和支付
- 斯坦福发布首份 AI Index 报告,AI 研究者不再茫然
- jQuery仿极客公园火箭发射“返回顶部”效果(初始篇)
- Java程序员必读,Java设计模式应该遵循哪些原则
- Visual Studio 2010快速参考指南里头的Scrum海报
- TFS2010 Team Project Collections
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用tensorflow-serving部署模型
- JVM详解之:java class文件的密码本
- Sharding-Proxy的基本功能使用
- JVM详解之:运行时常量池
- Linux常用命令面试题(1)
- 机器学习必刷题-手撕推导篇(1)
- Python面试必刷题系列(3)
- Spark Love TensorFlow
- 用GPU加速Keras模型——Colab免费GPU使用攻略
- __init__和__new__的对比及单例模式
- 数据结构高频面试题-树
- Python面试必刷题系列(5)
- 外卖小哥
- 用 Python可视化神器 Plotly 动态演示全球疫情变化趋势
- 2个范例带你读懂TensorFlow2低阶API构建模型方法