Webservice客户端使用一个WebMethod时,如果WebMethod内部出现异常,不管异常是系统级异常或者自定义的异常,均会被包装为SoapException类型的异常,返回给客户端。 客户端再使用这种SoapException时,无法直接从异常类的属性中提取直接的业务异常信息。
网上看到有同学是做了一个SoapException的Helper类,利用正则表达式的方式,从SoapException的属性做文法分析,从中提取业务异常信息。可是感觉这种方法不是很.Net,而且是不保险的一种做法,如果是自定义异常之类的,在做文法分析时可能会有隐患。而且不能更好的体现错误号。
仔细研究了SoapException之后,发现它有个detail属性,可以利用这个Xml文档类型的节点实现较好的异常信息封包。
步骤如下:
一、(服务端)建立 SoapException 的封包方法
///
<summary>
/// 异常类型
/// </summary>
public enum FaultCode
{
Client = 0 ,
Server = 1
}
/// <summary>
/// 封装异常为SoapException
/// </summary>
/// <param name="uri"> 引发异常的方法uri </param>
/// <param name="errorMessage"> 错误信息 </param>
/// <param name="errorNumber"> 错误号 </param>
/// <param name="errorSource"> 错误源 </param>
/// <param name="code"> 异常类型 </param>
/// <returns> 封装后的SoapException </returns>
public SoapException RaiseException(
string uri,
string errorMessage,
string errorNumber,
string errorSource,
FaultCode code
)
{
// 初始化限定名
XmlQualifiedName faultCodeLocation = null ;
// 异常类型代码转换
switch (code)
{
case FaultCode.Client:
faultCodeLocation = SoapException.ClientFaultCode;
break ;
case FaultCode.Server:
faultCodeLocation = SoapException.ServerFaultCode;
break ;
}
// 构建异常信息结构体
string strXmlOut = @" <detail> "
+ " <Error> "
+ " <ErrorNumber> " + errorNumber + " </ErrorNumber> "
+ " <ErrorMessage> " + errorMessage + " </ErrorMessage> "
+ " <ErrorSource> " + errorSource + " </ErrorSource> "
+ " </Error> "
+ " </detail> " ;
// 装载为Xml文档
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(strXmlOut);
// 实例化SoapException
SoapException soapEx = new SoapException(errorMessage, faultCodeLocation, uri, xmlDoc.DocumentElement);
// 返回SoapException
return soapEx;
}
/// 异常类型
/// </summary>
public enum FaultCode
{
Client = 0 ,
Server = 1
}
/// <summary>
/// 封装异常为SoapException
/// </summary>
/// <param name="uri"> 引发异常的方法uri </param>
/// <param name="errorMessage"> 错误信息 </param>
/// <param name="errorNumber"> 错误号 </param>
/// <param name="errorSource"> 错误源 </param>
/// <param name="code"> 异常类型 </param>
/// <returns> 封装后的SoapException </returns>
public SoapException RaiseException(
string uri,
string errorMessage,
string errorNumber,
string errorSource,
FaultCode code
)
{
// 初始化限定名
XmlQualifiedName faultCodeLocation = null ;
// 异常类型代码转换
switch (code)
{
case FaultCode.Client:
faultCodeLocation = SoapException.ClientFaultCode;
break ;
case FaultCode.Server:
faultCodeLocation = SoapException.ServerFaultCode;
break ;
}
// 构建异常信息结构体
string strXmlOut = @" <detail> "
+ " <Error> "
+ " <ErrorNumber> " + errorNumber + " </ErrorNumber> "
+ " <ErrorMessage> " + errorMessage + " </ErrorMessage> "
+ " <ErrorSource> " + errorSource + " </ErrorSource> "
+ " </Error> "
+ " </detail> " ;
// 装载为Xml文档
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(strXmlOut);
// 实例化SoapException
SoapException soapEx = new SoapException(errorMessage, faultCodeLocation, uri, xmlDoc.DocumentElement);
// 返回SoapException
return soapEx;
}
二、(服务端)WebMethod的异常处理中调用此方法。例如:
///
<summary>
/// 根据ID读取人员信息
/// </summary>
/// <returns> 人员信息类 </returns>
[WebMethod(Description = " 根据ID读取人员信息 " )]
public PersonInfo WSReadPersonByID( int ID)
{
try
{
PersonMethod personMethod = new PersonMethod();
return personMethod.ReadPersonByID(ID);
}
catch (System.Exception ex)
{
throw RaiseException(
" WSReadPersonByID " ,
ex.Message,
" 1000 " ,
ex.Source,
FaultCode.Server
);
}
}
/// 根据ID读取人员信息
/// </summary>
/// <returns> 人员信息类 </returns>
[WebMethod(Description = " 根据ID读取人员信息 " )]
public PersonInfo WSReadPersonByID( int ID)
{
try
{
PersonMethod personMethod = new PersonMethod();
return personMethod.ReadPersonByID(ID);
}
catch (System.Exception ex)
{
throw RaiseException(
" WSReadPersonByID " ,
ex.Message,
" 1000 " ,
ex.Source,
FaultCode.Server
);
}
}
三、(客户端)建立SoapException的信息解析类
using
System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Web.Services.Protocols;
/// <summary>
/// SoapException 信息解析类
/// </summary>
public class SoapExceptionInfo
{
/// <summary>
/// 错误号
/// </summary>
public string ErrorNumber = string .Empty;
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage = string .Empty;
/// <summary>
/// 错误源
/// </summary>
public string ErrorSource = string .Empty;
/// <summary>
/// SoapExceptionInfo构造方法
/// </summary>
public SoapExceptionInfo()
{
}
/// <summary>
/// SoapExceptionInfo构造方法
/// </summary>
/// <param name="soapEx"> SoapException </param>
public SoapExceptionInfo(SoapException soapEx)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(soapEx.Detail.OuterXml);
XmlNode categoryNode = doc.DocumentElement.SelectSingleNode( " Error " );
this .ErrorNumber = categoryNode.SelectSingleNode( " ErrorNumber " ).InnerText;
this .ErrorMessage = categoryNode.SelectSingleNode( " ErrorMessage " ).InnerText;
this .ErrorSource = categoryNode.SelectSingleNode( " ErrorSource " ).InnerText;
}
}
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Web.Services.Protocols;
/// <summary>
/// SoapException 信息解析类
/// </summary>
public class SoapExceptionInfo
{
/// <summary>
/// 错误号
/// </summary>
public string ErrorNumber = string .Empty;
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage = string .Empty;
/// <summary>
/// 错误源
/// </summary>
public string ErrorSource = string .Empty;
/// <summary>
/// SoapExceptionInfo构造方法
/// </summary>
public SoapExceptionInfo()
{
}
/// <summary>
/// SoapExceptionInfo构造方法
/// </summary>
/// <param name="soapEx"> SoapException </param>
public SoapExceptionInfo(SoapException soapEx)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(soapEx.Detail.OuterXml);
XmlNode categoryNode = doc.DocumentElement.SelectSingleNode( " Error " );
this .ErrorNumber = categoryNode.SelectSingleNode( " ErrorNumber " ).InnerText;
this .ErrorMessage = categoryNode.SelectSingleNode( " ErrorMessage " ).InnerText;
this .ErrorSource = categoryNode.SelectSingleNode( " ErrorSource " ).InnerText;
}
}
四、(客户端)使用WebMethod时,使用 SoapException的信息解析类方法
public
PersonInfo ReadByID(
int
id)
{
try
{
WSDemoService ws = new WSDemoService();
ws.Credentials = System.Net.CredentialCache.DefaultCredentials;
return ws.WSReadPersonByID(id);
}
catch (SoapException soapEx)
{
SoapExceptionInfo soapExInfo = new SoapExceptionInfo(soapEx);
throw new System.Exception(soapExInfo.ErrorMessage);
}
catch (Exception ex)
{
throw ex;
}
}
{
try
{
WSDemoService ws = new WSDemoService();
ws.Credentials = System.Net.CredentialCache.DefaultCredentials;
return ws.WSReadPersonByID(id);
}
catch (SoapException soapEx)
{
SoapExceptionInfo soapExInfo = new SoapExceptionInfo(soapEx);
throw new System.Exception(soapExInfo.ErrorMessage);
}
catch (Exception ex)
{
throw ex;
}
}