首页 > 开发 > 综合 > 正文

C#:Web Service异常处理

2024-07-21 02:20:04
字体:
来源:转载
供稿:网友
在.net中实现web服务时,在web服务接口中产生的任何用户异常(非soapexception之外的异常)都被包装为soapexception传递给客户端,这使得难以采用通常的方式处理web service的异常。本文讲述如何通过soapexceptionhelper实现一致的异常处理。

web service的异常处理问题
在.net中实现web服务时,web服务接口中产生的任何用户异常(非soapexception之外的异常)都被包装为soapexception传递给客户端 ,用户错误信息放置在soapexception的message属性中。

下面的例子演示了一个soapexception封装的用户异常信息。webmethod接口testexception代码抛出一个invalidoperationexception:

[webmethod]
public void testexception() {
throw new invalidoperationexception("invalid operation.");
}

webmethod的客户端将捕获一个soapexception异常,message消息如下:



其中message消息包含一段“...-->[ 1 ]:[ 2 ] at ....”的信息,[1]为用户异常类,[2]为用户异常消息。而一个原始的soapexception(用new soapexception(...)的方式创建并抛出的异常)则没有这些信息,下面是一个原始的soapexception消息:



遗憾的是,目前的soapexception并没有提供更多直接的手段直接获取原来的异常信息,唯一包含的用户异常信息在message字符串中,对于使用web service作为分布式机制的应用系统来说是非常不方便的,调用者无法捕获原来的异常,难以获取用户友好的异常信息。同时,因为web service接口代理不再抛出原来的异常,应用的开发者需要考虑两套完全不同的异常处理机制,带来了程序结构的复杂性。

创建soapexception辅助类:soapexceptionhelper
soapexceptionhelper辅助类包含下列主要接口:

isuserexception:是否是一个userexception
userexception:返回原始的userexception
message:原始异常的错误消息。
获得原始的用户异常类和异常消息
通过正则表达式类我们可以获得原始的用户异常类和异常消息:

/// <summary>
/// 读取userexception信息。
/// </summary>
private void readuserexceptioninfo() {
//match user exception class
system.text.regularexpressions.matchcollection mc =
regex.matches(soapexception.message, "---> ([^:]+):");
if (mc.count >= 1) {
userexceptionclass = mc[0].groups[1].value;
//match user exception message
mc = regex.matches(soapexception.message, "---> [^:]+:(.*)/n");
if (mc.count > 0) userexceptionmessage = mc[0].groups[1].value;
}
}

创建用户异常实例
userexception接口利用反射机制创建一个原来的exception类实例:

... ...
assembly callingassemply = assembly.getcallingassembly();
type exceptiontype = getexceptiontype(callingassemply); //获得用户异常类型定义
exception e = null;
try {
try {
e = activator.createinstance(exceptiontype, new object[]{userexceptionmessage}, null) as exception;
}
catch {}
//if no exists constructor with message parameter, use no parameters constructor.
if (e == null) e = activator.createinstance(exceptiontype) as exception;
}catch(exception ex) {
throw new soapexceptionhelperexception(userexceptionclass, ex);
}

return e;

创建用户异常的问题
因为用户异常可能定义在不同的集成块中,soapexceptionhelper可能无法知道它的位置,无法正确的获取异常类型,如一个与soapexceptionhelper所在集成块和调用集成块(callingassembly)不再同一个引用范围内的异常类。soapexceptionhelper如果无法创建原始异常的实例,就创建一个system.exception对象实例。

为了创建真正的原始异常类,调用者可以在外部获得实际的异常类型,并传递给soapexceptionhelper,因为调用者可以明确的引用异常定义 所在的集成块。示例如下:

// 项目引用中引入异常定义所在的集成块
...
soapexceptionhelper helper = new soapexceptionhelper(se);
type type = type.gettype(helper.userexceptionclass, "<异常类所在的集成块>");
exception e = helper.getuserexception(type);

如果外部没有传递异常类型定义,soapexceptionhelper尝试以以下顺序获取异常类型定义:

executing assembly
calling assembly
referenced assemblies (of calling assembly)
system.exception
使用soapexceptionhelper
返回用户友好的消息
使用soapexceptionhelper显示示例1中的错误消息:

try {
... ... // call web method
} catch (soapexception se){
messagebox.show(new soapexceptionhelper(se).message) ; //show "invalid operation." string
}
 

屏蔽soapexception
web service客户端代理类可以在捕获soapexception后重新抛出原来的异常,使用这种机制,可以有效的屏蔽web service异常处理的差异,使应用程序采用一致的本地方式处理异常。下面的代码修改visual studio生成的web service client proxy class(reference.cs文件)实现了这种机制(加粗的部分为新增的代码):

[system.web.services.protocols.soapdocumentmethodattribute("http://tempuri.org/testexception", requestnamespace="http://tempuri.org/", responsenamespace="http://tempuri.org/", use=system.web.services.description.soapbindinguse.literal, parameterstyle=system.web.services.protocols.soapparameterstyle.wrapped)]
public void testexception() {
try{
this.invoke("testexception", new object[0]);
}catch(soapexception se){
soapexceptionhelper helper = new soapexceptionhelper(se);
if (helper.isuserexception) throw helper.userexception; //rethrow user exception
else throw;
}
}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表