我正在尝试在使用iis和net.tcp的WCF服务中实现IErrorHandler。
我设置了一个场景,在服务器中抛出DivideByZeroException。 IErrorHandler按预期启动。
FaultException没有返回到客户端,我收到超时异常。我也在事件日志中找不到任何信息/异常。
这是演示代码。 http://www.fileswap.com/dl/gQFlVsZK7M/(请点击慢下载图片)
编辑1(从档案中添加代码供所有人查看):
服务合同:
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(DivideByZeroException))]
string GetData(int value);
[OperationContract]
[FaultContract(typeof(DivideByZeroException))]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}
服务实施:
public class Service1 : IService1
{
public string GetData(int value)
{
int i = 0;
//division by zero!
int y = 10/i;
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
IErrorHandler实现:
public class WcfErrorHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
var v = error as DivideByZeroException;
if (v != null)
fault = Message.CreateMessage(
version,
new FaultException<DivideByZeroException>(v, new FaultReason(v.Message)).CreateMessageFault(),
"http://the.fault.action");
}
public bool HandleError(Exception error)
{
return true;
}
}
答案 0 :(得分:0)
ConsoleApplication1中的ServiceReference未更新且不包含错误契约属性。当您将.NET用于服务和客户端时,最好在它们之间共享DataContract和ServiceContract。
对于测试,您可以在ConsoleApplication1应用程序中引用WcfService1库。执行此操作时,请按照以下步骤操作:
ConsoleApplication1中的app.config:
<client>
<endpoint address="net.tcp://localhost/WcfService1/Service1.svc"
binding="netTcpBinding"
contract="WcfService1.IService1" name="NetTcpBinding_IService2">
</endpoint>
</client>
客户代码:
try
{
var fact = new ChannelFactory<WcfService1.IService1>("NetTcpBinding_IService2");
var proxy = fact.CreateChannel();
var ves = proxy.GetData(1);
Console.WriteLine(ves);
}
catch (FaultException<DivideByZeroException> exp)
{
Console.WriteLine(exp.Detail);
}
服务代码(我更喜欢捕获异常,尽可能接近代码,然后引发具体的错误异常):
public string GetData(int value)
{
try
{
int i = 0;
int y = 10/i;
return string.Format("You entered: {0}", value);
}
catch (DivideByZeroException d)
{
throw new FaultException<DivideByZeroException>(d);
}
}
您的IErrorHandler:
public class WcfErrorHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error is FaultException)
{
//do nothing as it's already FaultException
//you should do a transformation only in the case it's required
}
else
{
// Generate fault message manually including the exception as the fault detail
MessageFault messageFault = MessageFault.CreateFault(
new FaultCode("Sender"),
new FaultReason(error.Message),
error);
fault = Message.CreateMessage(version, messageFault, null);
}
}
public bool HandleError(Exception error)
{
//here you can log an exception
return true;
}
}
P.S。您似乎错误地托管了您的服务。为了测试它,我在ConsoleApplication1中引用了WcfService1。并做了以下:
在ConsoleApplication1的app.config中添加了这些行:
<services>
<service name="WcfService1.Service1" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="" binding="netTcpBinding" contract="WcfService1.IService1" />
<!--<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> -->
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost/WcfService1/Service1.svc"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="True" />
<errorHandler />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="errorHandler" type="WcfService1.ErrorHandlerExtension, WcfService1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
在客户打电话给服务之前,我已经开始服务了:
private static void Main(string[] args)
{
var host = new ServiceHost(typeof(WcfService1.Service1));
host.Open();
...