加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

[WCF]缺少一行代码引发的血案

发布时间:2020-12-16 09:11:24 所属栏目:asp.Net 来源:网络整理
导读:这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性。具体来说,这是一个关于如何自动为服务接口(契约)的每个操作添加FaultContract与WCF服务元数

这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性。具体来说,这是一个关于如何自动为服务接口(契约)的每个操作添加FaultContract与WCF服务元数据发布的问题。接下来通过一个简单的实例来说明这个因为少写了一行代码引发的血案。

一、手工添加FaultContract

WCF采用基于消息的通信方式,Endpoint的ABC三要素之一的契约(Contract)的本质就是定义消息的结构。契约不仅定义了正常请求和响应负载的结构,还定义了承载异常信息的响应消息的结构。为了让契约能够响应消息承载的错误信息,承载错误信息的类型需要利用FaultContractAttribute特性注册到服务接口的操作方法上。

   1: [ServiceContract]
   2: public interface IMyService
   3: {
   4:     [OperationContract]
   5:     [FaultContract(typeof(ServiceExceptionInfo))]
   6:     string GetData(int value);
   7: }
   8:? 
   9: class MyService : IMyService
  10: {
  11:     value)
  12:     {
  13:         var ex = new InvalidOperationException("Invalid operation...");
  14:         throw new FaultException<ServiceExceptionInfo>(new ServiceExceptionInfo(ex));
  15:     }
  16: }
  17:? 
  18: [DataContract]
  19: class ServiceExceptionInfo
  20: {
  21:     [DataMember]
  22:     string ExceptionType { get; set; }
  23:? 
  24:     [DataMember]
  25:     string Message { get; set; }
  26:     public ServiceExceptionInfo(Exception ex)
  27:     {
  28:         this.ExceptionType = ex.GetType().AssemblyQualifiedName;
  29:         this.Message = ex.Message;
  30:     }
  31: }

如下面的代码片段所示,由于GetData操作抛出的FaultException对象采用一个ServiceExceptionInfo来描述详细错误信息,所以我们在定义服务接口的时候需要利用FaultContractAttribute将ServiceExceptionInfo这个类型注册到GetData方法上。

二、利用自定义ServiceHost自动注册ServiceExceptionInfo类型

如果多个操作都需要注册这么一个ServiceExceptionInfo类型,这其实是一件很繁琐的事情。对于今天找我们作技术支持的那个项目来说,由于采用了我们提供的一个自动化异常处理框架,要求所有的操作都需要注册一个类似于ServiceExceptionInfo的类型来描述最终的错误消息。为了让具体的项目可以不用在每个操作上都添加一个FaultContractAttribute,我们自定义了一个ServiceHost来实现了对它的自动注册。如下所示的MyServiceHost模拟了FaultContract自动化注册的逻辑。

2: {
   4:     { }
protected override void OnOpening()
   8:         base.OnOpening();
  10:         {
);
  13:             {
  15:                 {
  17:                     fault.DetailType = typeof(ServiceExceptionInfo);
  19:                 }
  21:         }
  23: }
  25: class MyServiceHostFactory : ServiceHostFactory
  27:     override ServiceHost CreateServiceHost(Type serviceType,Uri[] baseAddresses)
return new MyServiceHost(serviceType,baseAddresses);
<system.serviceModel>
   6:         serviceDebug includeExceptionDetailInFaults   7:       </   8:        9:     10:   servicesservice name="WcfService.MyService"  12:       endpoint binding="basicHttpBinding" contract="WcfService.IMyService"  13:     service  14:     15:   serviceHostingEnvironment   16:     serviceActivations  17:       add ="WcfService.MyService" relativeAddress="myservice.svc" factory="WcfService.MyServiceHostFactory"  18:       19:   serviceHostingEnvironment>    
  17:                     fault.Name = "ServiceExceptionInfoFault";
  20:                 }
  22:         }
  24: }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读