WCF从理论到实践(10):异常处理

本文目的

通过阅读本文,您能理解以下的知识

1) WCF中存在哪几种异常处理方式?
2) 各种异常处理所适用的应用场合?
3) WCF中常见的异常类型?
4) 代码不骗人,用示例来演示效果,加深印象

本文适合的读者

本文适合WCF的初学者,但要求对WCF有一些了解,并实现过简单的服务/客户端。


WCF中存在哪几种异常处理方式?

WCF定义了几种异常处理模型,它们分别如下:

1) 缺省模式
2) 包含详细信息模式
3) 自定义异常消息模式

各种异常处理所适用的应用场合?

1) 缺省模式

缺省情况下,服务端发生异常,客户端会得到一个缺省的Exception,但这个Exception实例中并不包括详细的异常信息。只是告诉客户端服务端不能正常工作。在服务器和客户端模式的程序中,有些情况下,服务启是不能完全信赖客户端的,比如浏览器和web服务器之间,为了防止非法的客户端从异常消息中获取服务端的比较详细的信息,使得心怀叵测之人有机可乘,所以服务启对于异常 返回通常会比较模糊。WCF也采用了这种做法,缺省情况下,它返回给客户端的异常只告知我出错了,但不告诉人家他哪里错了。这通常应用于客户端来源不明的生产环境,以此保护服务程序。  

2) 包含详细信息模式

如果想消息更友好一些,可以通过IncludeExceptionDetailInFaults=True来设置返回具体的异常信息,这样就能告诉客户端服务出错了,并指出错误出在哪里。在程序开发阶段或者有些应用场合,客户端是受信任的,为了让客户端能更详尽的了解服务端到底出了什么问题,WCF也支持发送详细的错误消息给客户端,这更有利于应用程序调试。而返回详细异常有两种方法:第一种:通过在服务端的配置文件中设置:<serviceDebug includeExceptionDetailInFaults="False" />,第二种方式为通过在代码中指定:[ServiceBehavior(IncludeExceptionDetailInFaults=true)]

3) 自定义异常消息模式

在WCF中,还支持更详细的异常消息,它通过自定义的异常消息FaultMessage来传达更多的内容。WCF采用通用的Soap Fault来处理异常,并提供了FaultException和FaultException<FaultMessage>两个类型来描述和操作异常。

WCF中常见的异常类型?

WCF包括三种常见类型的异常:

1) 通讯异常,这通常是因为链路的原因,比如服务没有启动,网络阻塞等。这类异常是CommunicationException或者其派生类
2) 状态异常,这类异常通常是与上文提到的实例模式相关的,当访问了一个已经销毁的服务器对象时便会引发此类型的异常,它们通常是ObjectDisposedException
3) 服务异常,由服务端根据具体的业务逻辑触发,通常是FaultException 值得注意的是当抛出服务异常的时候,不同的实例模式的处理方式有所不同:

PerSession:这种模式下,抛出异常,服务实例将销毁,客户端抛出FaultException,客户端代理对象无法继续使用

PerCall:这种模式下,抛出异常,服务实例也将销毁。客户端代理对象无法继续使用

Single:这种模式下,抛出异常,服务实例会照旧运行。客户端代理无法继续使用。

代码不骗人,用示例来演示效果,加深印象

本文所实现的实例非常简单,目的就是想验证一下各种异常处理方式下的不同表现。

1) 缺省模式

在示例中,我们这样抛出异常 

public string GetWelcomeInfo([ParaAtt(CanSetNull=false)] string name) 



ParameterInfo para 
= MethodInfo.GetCurrentMethod().GetParameters()[0]; 

ParaAtt att 
= ParaAtt.GetCustomAttribute(para, typeof(ParaAtt)) as ParaAtt; 

if (!att.CanSetNull && name == null



throw new Exception("参数不能设置为null"); 

}
 

return "Hello," + name; 

}
 

而此时,我们运行客户端,可以发现如下的运行结果:

从结果可以看出,缺省情况下,虽然客户端跑出了异常,但这些异常消息是不呈献给客户端的

2) 包含详细信息模式

将服务端配置文件中的<serviceDebug includeExceptionDetailInFaults="True" />,再次启动,此时客户端不但能收到和上图一致的跟踪堆栈信息,不同的是异常消息也会呈现给客户端

3)  自定义异常消息模式

这种模式是异常处理中相对最难的,因为它更加灵活,我们首先定义一个用于表示错误消息的数据契约ExceptionMsg,如下:

using System; 

using System.Collections.Generic; 

using System.Linq; 

using System.Text; 

using System.Runtime.Serialization; 

 

namespace Jillzhang.Wcf.ExContracts 



[DataContract] 

public class ExceptionMsg 



/// <summary> 

/// 异常消息文本 

/// </summary> 


[DataMember] 

public string Message getset; } 

 

/// <summary> 

/// 异常编码 

/// </summary> 


[DataMember] 

public string ErrorCode getset; } 

}
 

}
 

在定义操作的时候,我们可以指定返回的异常消息的类型,方法如下: 

[OperationContract] 

[FaultContract(
typeof(ExceptionMsg))] 

int Devide(int x, int y); 


运行实例程序,可以得到如下的结果:

我们可以用tcpTrace来跟踪下异常消息,有关如何跟踪WCF的Soap消息,前面文章WCF从理论到实践二:决战紫禁之巅 有所描述。本文讲述例外一种方法用于跟踪basicHttpBinding,为此我们要准备一款工具,Trace Utility,它是Microsoft SOAP Toolkit Version 3中的一个工具,利用它可以清晰地看到SoapMessage,方式如下:打开Trace Utility,选择菜单项File-Formated Trace,在接下来的对话框中填写要监听的端口和服务的端口,如下图所示:

点击确定后,将原来客户端端中的服务地址由

更改为

启动,便可以在Trace Utility中跟踪到SoapMessage,如下:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 

<s:Body> 

<s:Fault> 

<faultcode>s:Client</faultcode> 

<faultstring xml:lang="zh-CN">The creator of this fault did not specify a Reason.</faultstring> 

<detail> 

<ExceptionMsg xmlns="http://schemas.datacontract.org/2004/07/Jillzhang.Wcf.ExContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 

<ErrorCode>001</ErrorCode> 

<Message>除数不能为0</Message> 

</ExceptionMsg> 

</detail> 

</s:Fault> 

</s:Body> 

</s:Envelope> 

另外很多人不清楚如何调试跟踪WCF应用程序,特别是想从客户段跟踪到服务中,可以通过以下步骤来完成:

本文参考资料

  1. http://www.rainsts.net/article.asp?id=430

本文示例项目:

 /Files/jillzhang/Jillzhang.Wcf.ExceptionHandler.rar

作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Tag标签: WCF,异常处理
posted @ 2008-03-08 20:51 Robin Zhang 阅读(4771) 评论(15)  编辑 收藏 网摘 所属分类: WCF

  回复  引用    
#1楼2008-03-08 21:33 | antsB[未注册用户]
ohye .有空看看。
  回复  引用    
#2楼2008-03-09 00:22 | 学习了[未注册用户]
不错学习下
  回复  引用  查看    
#3楼[楼主]2008-03-09 07:35 | jillzhang      
@antsB
@学习了
多谢支持,这篇前面介绍的比较基础,但下面有两个技巧
1) 通过trace utility跟踪soapmessage
2) 如何调试wcf

  回复  引用  查看    
#4楼2008-06-17 08:50 | flank.chen      
是不错。
  回复  引用    
#5楼2008-09-05 17:07 | 11111111111[未注册用户]
你代码的解决方案里没有web项目,怎么用web代理访问?
  回复  引用  查看    
#6楼[楼主]2008-09-08 09:33 | jillzhang      
@11111111111
web代理?
什么意思

  回复  引用    
#7楼2008-09-10 16:57 | 11111111111[未注册用户]
我是想说,如果我通过iis访问wcf的service,那解决方案中不需要一个web项目的宿主吗? 看你程序里好像没有服务的宿主,只有服务项目Jillzhang.Wcf.ExceptionHandler.
  回复  引用    
#8楼2008-09-10 17:09 | 11111111111[未注册用户]
错误:
Could not connect to http://localhost:8080/Jillzhang.Wcf.ExceptionHandler/. TCP error code 10061: 由于目标机器积极拒绝,无法连接。 127.0.0.1:8080.

  回复  引用    
#9楼2008-09-10 17:19 | 11111111111[未注册用户]
把Jillzhang.Wcf.ExceptionClient的app.config改为<endpoint address="http://localhost:8731/Jillzhang.Wcf.ExceptionHandler/",
和Jillzhang.Wcf.ExceptionHandler的app.config中端口配置的一样,就可以了.(下载的代码是是<endpoint address="http://localhost:8080/Jillzhang.Wcf.ExceptionHandler/")

请问组长, 像您这样用系统附加的wcf宿主和console,window服务,iis宿主在性能用法等上的区别.

  回复  引用  查看    
#10楼[楼主]2008-09-11 11:56 | jillzhang      
@11111111111
可能是你机器上8080端口已经被占用了结果吧

  回复  引用  查看    
#11楼[楼主]2008-09-11 11:58 | jillzhang      
@11111111111
系统附加的宿主叫自承载,主要方便开发人员调试
各种宿主都会享有响应类型应用程序的特性。比如iis的自动回收,内存800M限制等。windows service开机启动等特征

  回复  引用    
#12楼2008-11-19 14:57 | 反射[未注册用户]
用反射来调用wcf,wcf有异常,client能得到具体的信息吗
  回复  引用    
#13楼2009-05-26 11:52 | 冰红茶wcf
l楼主你好:
很感谢你的文章,关于异常我有个小小的疑问,希望你能给解答一下!

public int Devide(int x, int y)
{
if (y == 0)
{
ExContracts.ExceptionMsg exMsg = new Jillzhang.Wcf.ExContracts.ExceptionMsg();
exMsg.Message = "除数不能为0";
exMsg.ErrorCode = "001";
throw new FaultException<ExContracts.ExceptionMsg>(exMsg);
return 0;
}
return x / y;
}

如上代码。产生异常后,抛出后。程序仍然会运行到 return x / y;这里。产生异常,这个时候再按f5才可以再client端收到异常信息。如果再service端不按f5。是不是在client就不会受到异常信息呢?如果是这样的话。如果再运行的程序中的话。service就是崩溃掉。client是否就收不到异常消息了?如果我希望收到。如何来做呢?




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1096790




相关文章:

相关链接: