0

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

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

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

外部服务用来与内部服务通信的客户端对象肯定是被正确关闭和处理的。如何让内部服务的错误传播到客户端?

更新:

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

mscorlib.dll 中出现“System.ServiceModel.FaultException`1”类型的未处理异常

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

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!
      }
   }
}
4

2 回答 2

0

我的设计几乎与您完全相同,并且遇到了类似的问题(但不确定是否会崩溃!)。

如果我没记错的话,即使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);
}
于 2010-08-03T22:55:18.450 回答
0

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

这似乎只是一个问题FaultException<ValidationFault>。我可以毫无问题地重新投掷FaultExceptionFaultException<SomethingElse>对象。

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));
}
于 2010-08-04T08:30:02.817 回答