C# WebForms中如何将完整异常对象传递至错误处理页面?
如何将完整Exception对象传递到自定义错误处理页面?
我正在创建自定义错误处理页面(如Oops.aspx),希望能把完整的Exception对象传递过去,这样就能在页面里分析错误(比如遍历StackTrace的帧)、记录错误,同时给用户展示友好提示。
之前尝试过几种方法都有问题:
- 直接用Response.Redirect传递对象,出现换行错误
- 用HttpUtility.UrlEncode把对象转字符串,行不通
- 直接转字符串会丢失大量数据
- 目前只能传递零散的字符串字段,但能获取的信息远不如完整对象多
示例代码(期望的错误分析逻辑)
var stackTrace = new StackTrace(ex, true); var allframes = stackTrace.GetFrames().ToList(); foreach(var frame in allframes) { var filename = frame.GetFileName(); var linenumber = frame.GetFileLineNumber(); var method = frame.GetMethod(); var MethodName = method.Name; var Classname = frame.GetMethod().DeclaringType.ToString(); }
尝试过的代码(无效)
HttpContext.Current.Response.Redirect(String.Format("~/Oops.aspx/Error=?{0}",ex));
当前使用的代码(只能传递零散字段)
HttpContext.Current.Response.Redirect(string.Format("~/Oops.aspx?Error={0}&StackTrace={1}&InnerException={2}&Data={3}&Source={4}&TargetSite={5}&Hresult={6}", ex.Message, ex.StackTrace, ex.InnerException, ex.Data, ex.Source, ex.TargetSite, ex.HResult));
可行的解决方案
1. 使用Session存储Exception对象
把Exception存入Session后跳转,错误页从Session取出处理,完成后清理Session避免内存浪费。
错误发生时的代码:
HttpContext.Current.Session["ErrorException"] = ex; HttpContext.Current.Response.Redirect("~/Oops.aspx");
Oops.aspx后台处理代码:
protected void Page_Load(object sender, EventArgs e) { if (Session["ErrorException"] is Exception ex) { // 执行你的错误分析、记录逻辑 var stackTrace = new StackTrace(ex, true); var allframes = stackTrace.GetFrames().ToList(); foreach(var frame in allframes) { var filename = frame.GetFileName(); var linenumber = frame.GetFileLineNumber(); var method = frame.GetMethod(); var MethodName = method.Name; var Classname = frame.GetMethod().DeclaringType.ToString(); // 这里添加记录或展示逻辑 } // 处理完毕后移除Session中的对象 Session.Remove("ErrorException"); } }
注意:需确保网站已启用会话状态(如InProc模式),否则Session无法正常使用。
2. 使用Server.Transfer传递对象
Server.Transfer是服务器端页面跳转,不会发起新的HTTP请求,可通过Context.Items直接传递对象。
错误发生时的代码:
HttpContext.Current.Items["ErrorException"] = ex; HttpContext.Current.Server.Transfer("~/Oops.aspx");
Oops.aspx后台处理代码:
protected void Page_Load(object sender, EventArgs e) { if (Context.Items["ErrorException"] is Exception ex) { // 处理完整的Exception对象 var stackTrace = new StackTrace(ex, true); // ... 你的分析和记录逻辑 } }
注意:使用Server.Transfer后,浏览器地址栏不会更新为错误页的URL,用户看到的仍是原页面地址。
3. 序列化Exception到内存缓存
如果Session不可用,可将Exception序列化后存入内存缓存,通过URL传递缓存Key,错误页再取出反序列化处理。
错误发生时的代码:
using System.Text.Json; using System.Web.Caching; // 生成唯一缓存Key var errorKey = Guid.NewGuid().ToString(); // 序列化Exception(处理循环引用问题) var json = JsonSerializer.Serialize(ex, new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles }); // 存入缓存,设置5分钟过期时间 HttpContext.Current.Cache.Insert(errorKey, json, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration); // 跳转到错误页并传递Key HttpContext.Current.Response.Redirect($"~/Oops.aspx?errorKey={errorKey}");
Oops.aspx后台处理代码:
using System.Text.Json; protected void Page_Load(object sender, EventArgs e) { var errorKey = Request.QueryString["errorKey"]; if (!string.IsNullOrEmpty(errorKey)) { var cachedJson = HttpContext.Current.Cache[errorKey] as string; if (cachedJson != null) { // 反序列化回Exception对象 var ex = JsonSerializer.Deserialize<Exception>(cachedJson, new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles }); if (ex != null) { // 处理错误逻辑 var stackTrace = new StackTrace(ex, true); // ... } // 清理缓存 HttpContext.Current.Cache.Remove(errorKey); } } }
注意:Exception对象包含循环引用,序列化时需配置忽略循环引用;避免使用存在安全风险的BinaryFormatter,优先用JsonSerializer。
内容的提问来源于stack exchange,提问作者Michael Wood
相关产品推荐
相关产品推荐

