当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > 错误处理

ASP.NET
C# Quoted-Printable编码、解码
asp.net Google的translate工具翻译 API
.NET读取所有目录下文件正则匹配文本电子邮件
asp.net 半角全角转化工具
AjaxControlToolKit 显示浏览者本地语言的方法
asp.net HTML文件上传标签
ASP.NET 绑定DataSet中的多个表
ASP.NET 重定向的几种方法小结
Asp.Net 重定向必须要知道的一些资料
ASP.NET 导出到Excel时保留换行的代码
Asp.Net Cache缓存使用代码
document.getElementsByName和document.getElementById 在IE与FF中不同实现
GridView单元格合并
asp.net 大文件上传控件
asp.net 日期函数 某月的第一天和最后一天的日期
asp.net 时间类 一周的周一和周末的日期
C# javaScript函数的相互调用
asp.net membership 密码重设
"虚拟路径"..."映射到另一个应用程序,这是不允许的!
如何传值在2个页面之间 要求不刷新父页面,并且不能用Querystring传值

ASP.NET 中的 错误处理


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-23   浏览: 99 ::
收藏到网摘: n/a

两种方式:
一、返回错误信息和错误码,这样客户端可以把错误信息直接显示给用户,省去了解析错误码的烦恼。
服务器端实现:
下面的类解析错误码定义文件,并且把错误信息加入hastTable
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Web;
using System.Web.Caching;
using System.Collections;

namespace MeetingProxy.MeetingException
{
    
/// <summary>
    
/// 错误码的描述
    
/// </summary>

    public class ErrProcedure
    
{

        
private static Hashtable errMessages = new Hashtable();
        
public static Hashtable GetErrMessages()
        
{
            
if (CommonCache.Get("ErrMessage"as Hashtable == null)
            
{
                
string path = null;

                HttpContext context 
= HttpContext.Current;
                
if (context != null)
                    path 
= context.Server.MapPath("~ErrMessage.xml");
                
else
                    path 
= Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ErrMessage.xml");

                XmlDocument xdoc 
= new XmlDocument();
                xdoc.Load(path);
                
foreach (XmlNode child in xdoc.LastChild)
                
{
                    errMessages.Add(
int.Parse(child.LastChild.InnerText), child.FirstChild.InnerText);
                }

                CacheDependency cd 
= new CacheDependency(path);
                CommonCache.Max(
"ErrMessage", errMessages,cd);
                
return errMessages;

            }

            
else
            
{
                
return CommonCache.Get("ErrMessage"as Hashtable;
            }

        }




    }

}

错误码文件:
<?xml version="1.0" encoding="UTF-8"?>
<ErrMessage>
  
<Err>
    
<Description>登录会议室错误</Description>
    
<ErrCode>100</ErrCode>
  
</Err>
  
<Err>
    
<Description>您申请的会议室被别人抢用,会议室创建失败,请重新申请</Description>
    
<ErrCode>101</ErrCode>
  
</Err>
   
<Err>
    
<Description>必须有端口号</Description>
    
<ErrCode>200</ErrCode>
  
</Err>
  
  
<Err>
    
<Description>用户名或者密码错误</Description>
    
<ErrCode>300</ErrCode>
  
</Err>
</ErrMessage>

异常定义:
using System;
using System.Collections.Generic;
using System.Text;

namespace MeetingProxy
{
    
public class MeetingBaseException:ApplicationException
    
{
        
int errCode;
        
public MeetingBaseException(string message, int errCode)
            : 
base(message)
        
{
            
this.errCode = errCode;
        }

        
public MeetingBaseException(int errCode)
        
{
            
this.errCode = errCode;
 
        }

        
public int ErrCode
        
{
            
get return errCode; }
            
set this.errCode = value; }
        }

    }

}


异常抛出方式:
private string VerifySession()
        
{
            
string passport = null;
            
if (HttpContext.Current != null)
            
{

                    passport = HttpContext.Current.Session["Username"as string;
            

            }

            
if (passport == null)
            
{
                
//用户没有通过Session验证
                throw new MeetingBaseException(ErrProcedure.GetErrMessages()[301].ToString(), 301);
            }

            
            
return passport;
        }
客户端:
客户端如果检测到是MeetingBaseException就可以直接把错误信息显示给客户,而不用解析错误码。
缺点:虽然省去了错误码的解析,但是如果有多语言化问题,错误信息直接显示就不行了。
如果客户端想只显示某些错误信息给客户,这种方式也不方便。
二、只返回错误码,客户端去解析错误码,这样提供了,最大的灵活性。
实现:服务器省去了错误码的解析。
异常抛出方式:
throw new MeetingBaseException(108);
客户端实现:
下面是用到资源文件的例子,如果只有一种资源,就可以用ErrProcedure处理。
因为全局资源被编译为资源类,而错误码是数字,不能做标志符,因此把他做简单处理,正数前加“R”,负数加“R_”,修改后类似(简体资源):
<data name="R303" xml:space="preserve">
    
<value>用户名已经存在</value>
  
</data>
<data name="R_500" xml:space="preserve">
    <value>系统异常</value>
  </data>
处理方式:
public static string  GetErrInfo(int errCode)
    
{
        
string resourceKey;
        
if (errCode >= 0)
        
{
            resourceKey 
= "R" + errCode.ToString();
        }

        
else
        
{
            errCode 
= errCode * -1;
            resourceKey 
= "R_" + errCode.ToString();
        }

         
        Type t 
= typeof(Resources.Login);
        PropertyInfo pi 
= t.GetProperty(resourceKey);
        
return pi.GetValue(nullnull).ToString();
      

    }

此处用反射简化了很多,见http://www.cnblogs.com/bluewater/archive/2006/09/08/498660.html
我认为第二种方式在大多数情况下都比较好,如果是很小的项目,第一种方式会简单些。
webservice异常处理:
在webservice中抛出异常,让客户端去解析是很困难的,因为客户端可能是js,php等,对ws的封装很差。因此我认为好一些的异常处理应该这样:
返回结果分两种类型,一种是只包含简单的错误码:
using System;
using System.Collections.Generic;
using System.Text;

namespace YahooBase.Result
{
    
/// <summary>
    
/// 普通返回值
    
/// </summary>

    public  class SoapResult
    
{
        
private int errCode;
        
public SoapResult()
        
{ }
        
public SoapResult(int errCode)
        
{
            
this.errCode = errCode; 
        }

        
public int ErrCode
        
{
            
get
            
return errCode; }
            
set { errCode = value; }
        }

    }

}

web服务方法实现:
[WebMethod()]
public SoapResult FreeConfrence()
    
{
        
try
        
{
            mc.FreeConfrence();
            
return new SoapResult(0);
        }

        
catch (MeetingBaseException me)
        
{
            
return new SoapResult(me.ErrCode);

        }

        
catch (ApplicationException ae)
        
{
            Log4net.log.Error(ae);
            
return new SoapResult(-500);
        }


        
catch (Exception e)
        
{
            
if (e.InnerException != null)
            
{
                Log4net.log.Error(e.InnerException);
            }

            Log4net.log.Error(e);
            
return new SoapResult(-500);
        }

 
    }
另一种返回复杂结果:
先定义返回值类型如,HistoryFeeResult
using System;
using System.Collections.Generic;
using System.Text;

namespace YahooBase.Result
{
    
/// <summary>
    
/// 查询历史帐单信息
    
/// </summary>

    public class HistoryFeeResult:SoapResult
    
{
        
public HistoryFeeResult(int errCode):base(errCode)
        
{}
        
public HistoryFeeResult()
        
{}
       
public MonthFee[] MonthFeeList;
    }

    
public class MonthFee
    
{
       
public string MonthName;
       
public Category[] CategoryList;

    }

    
public class Category
    
{
        
public Category(decimal fee, string name)
        
{
            Fee 
= fee;
            Name 
= name;
        }

        
public Category()
        
{ }
 
       
public decimal Fee;
       
public string Name;

    }

}

web方法实现:
实现方式和第一种一样,只是如果有自定义异常,则调用HistoryFeeResult的只有错误码的构造函数。
如果调用成功会返回(Post方式):
  <?xml version="1.0" encoding="utf-8" ?> 
<HistoryFeeResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  
<ErrCode>0</ErrCode> 
<MonthFeeList>
<MonthFee>
  
<MonthName>三月</MonthName> 
<CategoryList>
<Category>
  
<Fee>44.6</Fee> 
  
<Name>市话</Name>