I have this simple test project just to test the IncludeExceptionDetailInFaults behavior.
public class Service1 : IService1
{
public string GetData(int value)
{
throw new InvalidCastException("test");
return string.Format("You entered: {0}", value);
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
In the app.config of the service i have it set to true
<serviceDebug includeExceptionDetailInFaults="True" />
开发者_开发问答
On the client side:
try
{
using (var proxy = new ServiceReference1.Service1Client())
Console.WriteLine(proxy.GetData(5));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
This is what I thought the behavior was: Setting to includeExceptionDetailInFaults=true would propagate the exception detail to the client. But I'm always getting the CommunicationObjectFaultException.
I did try having the FaultContract(typeof(InvalidCastException)) on the contract but same behavior, only getting the CommunicationObjectFaultException.
The only way to make it work was to throw new FaultException(new InvalidCastException("test"));
But I thought with IncludeExceptionDetailInFaults=true the above was done automatically.
Am I missing something?
It's because you've put the service client inside a using
block.
WCF clients are the one place in .NET where you shouldn't use using
, because it will mask the "real" exception.
Technical explanation: Dispose
calls Close
, which will always throw a CommunicationObjectFaultedException
if the channel is already faulted (i.e. as a result of a previous exception), which subsequently puts that exception at the top of the stack. When cleaning up an ICommunicationObject
, in order to avoid masking the exception, you have to first check the State
to see if it is faulted, and if so call Abort
instead of Close
.
精彩评论