我有一个托管在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!
}
}
}
答案 0 :(得分: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);
}
答案 1 :(得分:0)
嗯,如果我这样做会有效,但必须有更好的方法......
这似乎只是FaultException<ValidationFault>
的一个问题。我可以毫无问题地重新抛出FaultException
和FaultException<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));
}