由客户端不视为相同类型的 Web 服务引发的自定义异常(使用共享程序集)

Posted

技术标签:

【中文标题】由客户端不视为相同类型的 Web 服务引发的自定义异常(使用共享程序集)【英文标题】:Custom Exception Thrown by a Web Service not seen as same type by the Client (using shared assemblies) 【发布时间】:2014-03-09 20:26:26 【问题描述】:

我创建了一个自定义异常InvalidSessionException。但是,当尝试捕获或评估引发的异常是否属于该类型时,它不起作用。这意味着 EX isCatch Ex,不要评估为 InvalidSessionException

try 

    acc = this.fda.GetAccountHeader(this.selectedTicket.AccountId);
  
catch (Exception ex) 

    if (ex is Enterprise.Data.InformationModel.CustomExceptions.InvalidSessionException) 
    
        this.lblError.Text = Resources.Resource.error_sessionedTimedOut;
        this.MPError.Show();
    
    return;

我也尝试过(结果没有任何差异)

catch (Enterprise.Data.InformationModel.CustomExceptions.InvalidSessionException ex) 

    this.lblError.Text = Resources.Resource.error_sessionedTimedOut;
    this.MPError.Show();
    return;
 
catch (Exception ex) 

    return;

据我所知,抛出的异常是正确的类型。

更多信息:

ex.GetType().FullName = "System.ServiceModel.FaultException1[[System.ServiceModel.ExceptionDetail, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

服务上启用了重用类型?

【问题讨论】:

调试器似乎显示它是一个InvalidSessionException。还有什么让您认为它不被认可? 在评估 'Catch' 或 'Is' 时它永远不会命中代码 是的,来自网络服务 那么实际上您并没有捕获该异常,而是另一个具有相同命名空间和类名的异常(除非您将原始程序集部署到客户端并重用类型)。有关更多详细信息,请参阅this post。 @owengerig 我不认为很容易看出区别,只是尝试看看 ex.GetType().FullName 是什么。程序集是否在客户端共享并且您明确设置为使用它们?默认情况下,即使有对该 DLL 的引用,它也不会重用类型。 【参考方案1】:

信用到期的信用 此答案的百分之九九分归功于Adriano Repetti 在此页面上留下的评论。我刚刚自己测试了这个解决方案,因为我遇到了与上面问题中描述的完全相同的问题。

问题 参考“配置服务参考”模式窗口;仅仅因为您选择“在所有引用的程序集中重用类型”并不意味着它实际上会这样做——这似乎是一个惰性操作,基本上,如果自动生成代码发生匹配它。解决方案 因此,如果您真的勾选了您关心的内容,似乎可以保证使用它而不是 maybe。这是通过将单选按钮从“在所有引用的程序集中重用类型”更改为“在指定的引用的程序集中重用类型”(第二个单选按钮选项)来实现的。

我的支持意见 似乎这特别影响了 FaultExceptions,我不知道为什么,但确实如此。我的项目中的 FaultExceptions 是在服务引用的命名空间下生成的,而不是从引用的程序集中重新使用它们。 特别令人费解的是,在查看服务参考代码的Reference.cs时,专门描述了namspace。即便如此,直到我做了上面描述的事情,它才起作用。最后我只想指出,这是一个很好的“打破规范”或“不规范”的例子。

【讨论】:

【参考方案2】:

我相信你需要使用强类型FaultException<T>。比如……

免责声明:以下代码未经测试

服务器端

[ServiceContract]
public interface ISampleService

  [OperationContract]
  [FaultContractAttribute(typeof(InvalidSessionException)]
  void SampleMethod();


void SampleMethod()

  ...
  throw new FaultException<InvalidSessionException>();

客户端

...

try

   _wcfChannel.SampleMethod();

   catch (FaultException<InvalidSessionException> ex)
   
      // take appropriate action
   

补充阅读

MSDN:FaultException remondo.net:Using WCF Typed Fault Exceptions(一个简单的例子) iDesign:WCF Fault Contract(示例代码) 代码项目:A Beginner's Tutorial for Understanding Exception Handling, FaultExceptions and FaultContracts in WCF

【讨论】:

从设计的角度来看,我个人不喜欢将我的服务器端代码耦合到 WCF 的想法。我宁愿抛出一个 normal 异常,然后在它进入 WCF 通信通道之前将其转换为 FaultException&lt;T&gt;。不知道这将是多么容易/难实现。 这是我采用的最新方法,但它仍然没有在正确的 catch 语句中捕获它,它总是使用通用的方法,即。 catch (exception ex) 而不是 catch (FaultException ex) . 我已经使用了上述方法,并且效果非常好。需要考虑的一些事项: (1) 捕获异常的顺序无关紧要 - 首先放置更具体的异常。 (2) FaultContractAttribute 属性是否已分配给适当的服务器端方法? (3) 考虑构建一个小型演示应用程序来测试实现——这将消除“噪音”并使您的问题更容易解决。 (4) 我的记忆很模糊......但您可能必须通过服务器端配置启用自定义 WCF 异常 - 请查看 MSDN 文档。 如果在 catch 块内设置断点,然后在 Visual StudioWatch 窗口中尝试以下操作会发生什么情况:ex as FaultException

以上是关于由客户端不视为相同类型的 Web 服务引发的自定义异常(使用共享程序集)的主要内容,如果未能解决你的问题,请参考以下文章

Jersey REST 客户端 - 将自定义 MediaType 视为 MediaType.APPLICATION_JSON

不同的重写动态 slug 被视为重复

MYSQL的自定义函数

IIS7动态内容压缩和Web服务

WCF 服务中的自定义证书验证

如何跟踪我的 Web 服务引发的 IIS 500 错误