开发者社区> 技术小牛人> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

在WCF中的异常处理方法

简介:
+关注继续查看
在 WCF 中,客户端调用服务时,可能抛出的异常有以下三种类型。

1. 通讯异常。诸如网络错误,地址错误,服务器没有启动等等。这类异常多是 CommunicationException (或其具体继承类型)。
2. 状态异常。比如访问了已经关闭的代理对象,契约错误,以及安全设置错误等。常见的有 ObjectDisposedException。
3. 服务异常。由服务器触发,多是 FaultException。

针对服务异常,不同的实例管理方式会有不同的策略。

1. Pre-Call: 服务实例被释放,客户端抛出 FaultException,客户端代理对象无法继续使用。
2. Pre-Session: 服务实例被释放,会话终止。客户端抛出 FaultException,客户端代理对象无法继续使用。
3. Singleton: 服务实例依旧运行,会话终止。客户端抛出 FaultException,客户端代理对象无法继续使用。

基于平台中立和技术整合的需要,WCF 以标准 Soap Faults 方式传递异常信息。WCF 提供了 FaultException 和 FaultException<T> 两个类型来操控 Soap Faults。通过 FaultException<T> 我们可以向客户端传递一个错误信息(FaultReason)以及一个附加的详细信息(Detail)。理论上,这个附加信息是任何可以序列化的对象。
throw new FaultException<int>(123, "abc");
throw new FaultException<Exception>(new Exception("abc"));

如果想传递一个附带元数据的自定义详细信息,可以使用 FaultContract。
[DataContract]
public class ExceptionData
{
  [DataMember]
  public string Message;
}

[ServiceContract]
public interface IService
{
  [OperationContract]
  [FaultContract(typeof(ExceptionData))]
  void Test();
}

public class Service : IService, IDisposable
{
  public void Test()
  {
    ExceptionData d = new ExceptionData();
    d.Message = "xxxxxx";

    throw new FaultException<ExceptionData>(d, "abc");
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}

当然,我们也可以直接抛出一个被称之为 "Unknown Faults" 的 FaultException 异常实例。还有另外一种情况,你已经写好了代码,有很多……很多……的代码,要是一个个修改会非常……非常……麻烦,那么怎么在不做大的代码修改情况下传递详细异常信息给客户端呢?

方法1: ServiceBehavior(IncludeExceptionDetailInFaults=true)]
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class Service : IService, IDisposable
{
  public void Test()
  {
    throw new Exception("abc");
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}

方法2: ServiceDebugBehavior

这个比方法1要更方便一些,我们除了可以写代码外,还可以用配置文件。
ServiceHost host = new ServiceHost(typeof(Service), new Uri("http://localhost:8080/Service"));
host.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), "");

ServiceDebugBehavior debug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
debug.IncludeExceptionDetailInFaults = true;

host.Open();

看看这两种方法抛出的异常是什么样的。
未处理 System.ServiceModel.FaultException`1
  Message="abc"
  Source="mscorlib"
  StackTrace:
    Server stack trace: 
      在 ConsoleApplication1.localhost.IService.Test()
      在 ConsoleApplication1.localhost.ServiceClient.Test() 位置 D:\...\localhost.cs:行号 60
      在 ConsoleApplication1.Program.Main(String[] args) 位置 D:\...\Program.cs:行号 62

不错,除了 Error Message,还有详细的 stack trace,方便调试。也正因为这样,此种方法也不适合在正式项目中使用,作为系统架构设计的一部分,我们应该事先设计好异常处理。

如果服务方法是 IsOneWay=true,因不接收返回消息,客户端也就不会触发异常了。而 Callback 无非是服务器和客户端掉换个身份而已,道理相同。
public interface ICallback
{
  [OperationContract]
  void DoCallback();
}

[ServiceContract(CallbackContract=typeof(ICallback))]
public interface IService
{
  [OperationContract]
  void Test();
}

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
public class Service : IService, IDisposable
{
  public void Test()
  {
    try
    {
      OperationContext.Current.GetCallbackChannel<ICallback>().DoCallback();
    }
    catch (FaultException e)
    {
      Console.WriteLine(e);
    }
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }
}
  

本文转自 高阳 51CTO博客,原文链接:http://blog.51cto.com/xiaoyinnet/196450 ,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
原文:WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理 在前面一片文章(服务代理不能得到及时关闭会有什么后果?)中,我们谈到及时关闭服务代理(Service Proxy)在一个高并发环境下的重要意义,并阐明了其根本原因。
599 0
WCF基础教程之异常处理:你的Try..Catch语句真的能捕获到异常吗?
  在上一篇WCF基础教程之开篇:创建、测试和调用WCF博客中,我们简单的介绍了如何创建一个WCF服务并调用这个服务。其实,上一篇博客主要是为了今天这篇博客做铺垫,考虑到网上大多数WCF教程都是从基础讲起的,大家平时工作可能只是去调用和修改WCF的一些方法,而并未创建和配置过WCF,如果大家通过网上的教程去一步一步的创建和配置WCF,中途遇到错误,特别是WCF的配置这块很容易出错,难免会浪费时间。
611 0
WCF方法拦截及OperationInvoker传递参数到WCF方法的实现
鉴于一些理由需要拦截WCF方法,比如参数的检测。一个实际的场景是CSRF防范中需要对CsrfToken的检测。要实现拦截,在形式上要实现两点:1:为WCF方法增加特性类;2:捕获WCF方法;第一点很好实现,实现一个Attribute类。
380 0
wcf异常处理
问个问题:WCF中的异常处理问题泠寒冰点: 服务器端抛出异常,让客户端捕获。 xx:直接在服务器端抛出,然后在WCF的配置文件中打开异常选项,在客户端就可以截获了  泠寒冰点: 我也知道啊。但是那个异常先在服务器端捕获了,然后,我必须要手动点下F5,客户端才捕获到。
441 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载