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

ASP.NET
asp.net GridView控件中模板列CheckBox全选、反选、取消
asp.net GridView 删除时弹出确认对话框(包括内容提示)
asp.net DropDownList 三级联动下拉菜单实现代码
asp DataTable添加列和行的三种方法
Asp.net 页面调用javascript变量的值
asp.net 长文章通过设定的行数分页
asp.net 定时间点执行任务的简易解决办法
asp.net 页面延时五秒,跳转到另外的页面
asp.net 动态输出透明gif图片
asp.net DataList与Repeater用法区别
asp.net Javascript获取CheckBoxList的value
asp.net程序在调式和发布之间图片路径问题的解决方法
asp.net下生成英文字符数字验证码的代码
asp.net 页面版文本框智能提示JSCode (升级版)
ASP.NET URL伪静态重写实现方法
ASP.NET 2.0 中Forms安全认证
asp.net 动态添加多个用户控件
asp.net Repeater显示父子表数据,无闪烁
asp.net 无法获取的内部内容,因为该内容不是文本 的解决方法
asp.net GridView排序简单实现

ASP.NET 中的 错误处理


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-23   浏览: 92 ::
收藏到网摘: 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>