【发布时间】:2012-01-13 00:34:58
【问题描述】:
我的 C# 中的 WCF 服务如下所示。
[ServiceContract]
public class MySecretService
{
[OperationContract]
[FaultContract(typeof(ErrorMessage))]
public MyDTO ReturnMyDTOMethod(int id, out string errorMessage)
{
try
{
//Do stuff...
//Do some more stuff... pseudocode
if (biz rule 1 && etc)
{
return MyDTO;
}
else if (biz rule 2 && etc)
{
return null;
}
else
{
throw new FaultException<ErrorMessage>(blah etc..)
}
}
catch (Exception e)
{
throw new FaultException<ErrorMessage>(blah etc...);
}
}//end-method
}//end-class
要从该方法返回的 DTO 如下所示:
[DataContract]
public class MyDTO
{
[DataMember]
public XElement XmlRep
{
get
{
//do something within setter, etc...
//error occurs prior to returnin from setter, where to i catch it?
return _xmlRep
}
set
{
_xmlRep = value;
}
}
}
我发现的典型示例显示了从方法中抛出 FaultException;但就我而言,我的方法没有错误;错误发生在对象被返回给客户/消费者的时候;即当 DataMember/Property XmlRep 被序列化时;
所以我不能将 throw FaultException 放在我的方法中;但我仍然想避免得到 “底层连接已关闭:连接意外关闭。”并抛出发生在 getter 中的正确错误。
我没有尝试将 try/catch 放在 MyDTO 的 getter 中,我也不想因为我希望我的 DTO 尽可能简单,并且对 FaultExceptions 和 WCF 的东西一无所知。还有其他想法吗?
编辑:为了更清楚,我知道错误发生在 MyDto DataContract 的 Getter 中;但是我还能在哪里抛出 FaultException,因为在我看来,在 Getter 内部是一个不可靠的地方来抛出它?
EDIT#2:我在服务端实现了一个包罗万象的错误处理程序,正如 Tim 下面所建议的那样(使用 IErrorHandler);这在我的具体情况下不起作用。我认为这是因为错误不会发生在 OperationContract ReturnMyDTOMethod() 中,而是在被序列化时发生在 MyDto 中;换句话说,看起来马已经跑了(方法成功返回),并且 IErrorHandler 有任何用途都为时已晚 - 具体来说,ProvideFault() 不会触发,但 HandleError() 会触发。因此,我仍然收到一条频道中断消息,这需要我回到绘图板 - 即确保 MyDto 不会做任何花哨的事情,例如产生错误!
【问题讨论】:
-
不要随便提到你得到一个错误,就好像它是无关紧要的,请完整发布你的异常!
-
@hugh,请重新阅读问题;我认为很清楚,错误是“底层连接已关闭:连接意外关闭。”此错误出现在消费者/客户端。
-
@joedotnot - 您可以通过 IErrorHandler 的实现(下面我的答案中的选项 2)捕获异常并从那里抛出 FaultException,或者当您实例化 DTO 和扔掉它。
标签: wcf channel faultexception