假设我们有一个服务方法,它执行一些安全检查,从数据库和第三方Web服务中检索数据,构造MyDataDTO
,并将审核条目写回到数据库。 我们希望有良好结构化的、细粒度的错误代码,不是吗?我们是好孩子,按照标准的WCF错误处理指南操作:
[FaultContract(typeof(AccessDenied))]
[FaultContract(typeof(KeyNotFound))]
[FaultContract(typeof(WsFault))]
[FaultContract(typeof(DbFault))]
MyDataDTO GetData(string key);
现在我们正在添加一个更新数据的新方法。该方法内部调用GetData()
(或其主要部分),执行验证并更新数据。因此,它必须具有GetData()
的所有错误的副本以及自身的错误:
[FaultContract(typeof(InvalidState))]
[FaultContract(typeof(DataNotValid))]
[FaultContract(typeof(AccessDenied))]
[FaultContract(typeof(KeyNotFound))]
[FaultContract(typeof(WsFault))]
[FaultContract(typeof(DbFault))]
void UpdateData(MyDataDTO data);
到目前为止还不错。这甚至允许我们生成XML文档,以便我们可以向服务的消费者提供错误代码的信息。现在想象一下,我们有十个类似上述(或更复杂)的方法的10个服务。定义所有这些故障契约变成了噩梦,因为这是一个容易出错的过程:
1. 没有办法为整个服务定义一般故障(例如DbFault)。 2. 无法保证在操作契约中定义的故障确实会被返回(复制粘贴问题)。 3. 无法保证您没有错过添加到操作契约中的某些故障。
暂且不考虑接口版本控制的问题。
这就是您在生产中支持WCF服务时遇到的情况。我们应该完全放弃故障契约并使用老式的C样式(例如使用具有 ErrorCode 属性的基本DTOBase类)吗?降低错误粒度?如何确保文档正确/更新?我对一些最佳实践很感兴趣。
FaultException<string>
或FaultException<MessageFault>
,其中MessageFault
将是具有单个string
属性的FaultContract
。请注意,我不会返回任何错误代码,只返回要显示的字符串。 - John Saunders