【问题标题】:WCF FaultException - crashes App Pool when "re-throwing" from internal WCF callWCF FaultException - 从内部 WCF 调用“重新抛出”时应用程序池崩溃
【发布时间】:2011-03-24 18:15:41
【问题描述】:

我有一个托管在 IIS 中的 WCF 服务,并使用 WS HTTP 绑定(外部服务)。该服务最终通过 Net TCP(内部服务)调用 Windows 服务中托管的第二个 WCF 服务。当内部服务抛出FaultException 时,外部服务崩溃而不是抛出给客户端。客户端看到的只是连接被强制关闭。

内部服务使用企业库验证应用程序块来验证传入消息。发生验证错误时,服务会抛出FaultException<ValidationFault>

内部和外部服务在服务契约中都有一个[FaultContract(typeof(ValidationFault)] 属性。如果我将外部服务更改为立即抛出一个新的FaultException<ValidaitonFault>,这会很好地返回给客户端。我可以在外部服务中捕获来自内部服务的异常,但是如果我尝试重新抛出它,或者甚至将它包装在一个新的异常中并抛出它,IIS 中的整个应用程序池就会崩溃。我在事件日志中看不到任何有用的信息,所以我不确定到底是什么问题。

外部服务用于与内部服务通信的客户端对象肯定已正确关闭和处置。如何让内部服务的故障传播到客户端?

更新:

以下是外部服务代码的简化版本。我可以从内部服务调用中捕获验证错误。如果我抛出一个全新的FaultException<ValidationFault>,一切都很好。如果我使用捕获的异常,与外部客户端的连接就会中断。我能看到的唯一区别是在调试服务时 - 尝试使用捕获的异常会导致退出方法时出现一个消息框,上面写着

未处理的类型异常 'System.ServiceModel.FaultException`1' 发生在 mscorlib.dll 中

如果我抛出一个全新的异常,这不会出现。也许答案是手动将验证错误的详细信息复制到一个新对象中,但这似乎很疯狂。

public class ExternalService : IExternalService
{
   public ExternalResponse DoSomething(ExternalRequest)
   {
      try
      {
         var response = new ExternalResponse();
         using (var internalClient = new InternalClient())
         {
            response.Data = internalClient.DoSomething().Data;
         }

         return response;
      }
      catch (FaultException<ValidationFault> fEx)
      {
         // throw fEx;   <- crashes

         // throw new FaultException<ValidationFault>(
         //    fEx.Detail as ValidationFault);   <- crashses

         throw new FaultException<ValidationFault>(
            new ValidationFault(new List<ValidationDetail> {
               new ValidationDetail("message", "key", "tag") }),
               "fault message", new FaultCode("faultCode"))); // works fine!
      }
   }
}

【问题讨论】:

    标签: wcf validation application-pool


    【解决方案1】:

    我的设计几乎和你一模一样,但遇到了类似的问题(但不确定是否会崩溃!)。

    如果我没记错的话,即使ValidationFault 是一个通用类,当故障通过线路传输时,该类型也是特定于 WCF 接口的。我认为这是因为 Web 服务上的命名空间限定符(但这是前一段时间,所以我可能会弄错)。

    这不是很优雅,但我所做的是手动重新抛出异常:

    try
    {
        DoStuff();
    }
    catch (FaultException<ValidationFault> fe)
    {
        HandleFault(fe);
        throw;
    }
    
    ...
    
    private void HandleFault(FaultException<ValidationFault> fe)
    {
        throw new FaultException<ValidationFault>(fe.Detail as ValidationFault);
    }
    

    【讨论】:

    • 感谢您的建议,但不幸的是它没有奏效。如果有任何用处,我已经在问题中添加了更多细节。
    【解决方案2】:

    好吧,如果我这样做,它会起作用,但必须有更好的方法......

    这似乎只是FaultException&lt;ValidationFault&gt; 的问题。我可以毫无问题地重新抛出 FaultExceptionFaultException&lt;SomethingElse&gt; 对象。

    try
    {
       DoStuff();
    }
    catch (FaultException<ValidationFault> fe)
    {
       throw this.HandleFault(fe);
    }
    
    ...
    
    private FaultException<ValidationFault> HandleFault(
        FaultException<ValidationFault> fex)
    {
        var validationDetails = new List<ValidationDetail>();
        foreach (ValidationDetail detail in fex.Detail.Details)
        {
            validationDetails.Add(detail);
        }
    
        return new FaultException<ValidationFault>(
            new ValidationFault(validationDetails));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多