当跨越边界抛出错误异常时,可以采用类型参数来跨WCF边界传递详细信息对象。但是,我注意到当一个错误异常越过两个边界时(或者因为它被重新抛出,或者因为异常只是在堆栈中冒泡),细节对象就会丢失。这是设计的吗?如果是这样,为什么?
我有一个代码存储库,如果你想看看我在说什么,就会显示这个:
答案 0 :(得分:4)
非常有趣,它肯定看起来像WCF中的一个错误。如果我从命名管道切换绑定(和地址)以使用HTTP它实际上是有效的。我会向产品团队提交一个错误。感谢您报告此问题!
BTW,这是一个独立的控制台代码,可以重现这个问题。
public class StackOverflow_6267090
{
static bool useHttp;
const string baseAddressHttp = "http://localhost:8000/Bug/";
const string baseAddressPipe = "net.pipe://localhost/Bug/";
static Binding GetBinding()
{
if (useHttp)
{
return new BasicHttpBinding();
}
else
{
return new NetNamedPipeBinding();
}
}
static string GetBaseAddress()
{
return useHttp ? baseAddressHttp : baseAddressPipe;
}
[ServiceContract]
public interface IInner
{
[OperationContract]
[FaultContract(typeof(Detail))]
int DoStuff();
}
[ServiceContract]
public interface IOuter
{
[OperationContract]
[FaultContract(typeof(Detail))]
int DoStuff();
}
[DataContract]
public class Detail
{
[DataMember]
public string Data { get; set; }
public override string ToString()
{
return string.Format("Detail[Data={0}]", Data);
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class InnerService : IInner
{
public int DoStuff()
{
//return 3;
throw new FaultException<Detail>(new Detail { Data = "Something" }, new FaultReason("My special reason"));
}
}
class OuterService : IOuter
{
public int DoStuff()
{
return Caller.CallInner("In service");
}
}
public static class Caller
{
public static int CallInner(string where)
{
try
{
var factory = new ChannelFactory<IInner>(GetBinding(), new EndpointAddress(GetBaseAddress() + "Inner/"));
var channel = factory.CreateChannel();
int result = channel.DoStuff();
return result;
}
catch (FaultException<Detail> e)
{
Console.WriteLine("[{0} - CallInner] Error, Message={1}, Detail={2}", where, e.Message, e.Detail);
throw;
}
}
public static int CallOuter(string where)
{
try
{
var factory = new ChannelFactory<IOuter>(GetBinding(), new EndpointAddress(GetBaseAddress() + "Outer/"));
var channel = factory.CreateChannel();
int result = channel.DoStuff();
return result;
}
catch (FaultException<Detail> e)
{
Console.WriteLine("[{0} - CallOuter] Error, Message={1}, Detail={2}", where, e.Message, e.Detail);
throw;
}
}
}
public static void TestWith(bool useHttp)
{
StackOverflow_6267090.useHttp = useHttp;
Console.WriteLine("Using address: {0}", GetBaseAddress());
string baseAddress = GetBaseAddress();
ServiceHost innerHost = new ServiceHost(typeof(InnerService), new Uri(baseAddress + "Inner/"));
ServiceHost outerHost = new ServiceHost(typeof(OuterService), new Uri(baseAddress + "Outer/"));
innerHost.AddServiceEndpoint(typeof(IInner), GetBinding(), "");
outerHost.AddServiceEndpoint(typeof(IOuter), GetBinding(), "");
innerHost.Open();
outerHost.Open();
Console.WriteLine("Hosts opened");
Console.WriteLine("Calling inner directly");
try
{
Console.WriteLine(Caller.CallInner("client"));
}
catch (FaultException<Detail> e)
{
Console.WriteLine("In client, after CallInner, Message = {0}, Detail = {1}", e.Message, e.Detail);
}
Console.WriteLine("Calling outer");
try
{
Console.WriteLine(Caller.CallOuter("client"));
}
catch (FaultException<Detail> e)
{
Console.WriteLine("In client, after CallOuter, Message = {0}, Detail = {1}", e.Message, e.Detail);
}
catch (FaultException e)
{
Console.WriteLine("BUG BUG - this should not have arrived here. Exception = {0}", e);
}
}
public static void Test()
{
TestWith(true);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
TestWith(false);
}
}
答案 1 :(得分:0)
我尝试了你的示例代码 - 它对我来说很好。我运行了三个实例,并在一个内部托管,另一个托管在外部,然后从第三个托管内部和内部托管。在这两种情况下,我都看到了详细信息。