我有一个非常简单的3层项目。存在与数据存储交互的DAL(数据访问层)WCF服务; BLL(业务逻辑层)WCF服务,作为DAL服务与客户端UI和Windows窗体客户端层之间的中介。
我在DAL服务中声明DataContract作为错误合同:
[DataContract]
public class ValidationFault
{
[DataMember]
public String Message { get; set; }
[DataMember]
public String PropertyName { get; set; }
...
}
我的DAL服务有一个用FaultContract属性修饰的操作:
[OperationContract]
[FaultContract(typeof(ValidationFault))]
Patient CreatePatient(Patient patient);
CreatePatient的实现会抛出强类型的FaultException,如下所示:
throw new FaultException<ValidationFault>(new ValidationFault("Patient last name cannot be empty.", "LastName"));
我的BLL服务充当DAL服务的客户端和UI层的服务。在我的BLL服务中,我调用DAL服务的CreatePatient方法,如果我捕获到FaultException错误,我只想重新抛出它以供客户端处理。相关的BLL代码如下所示:
...
catch (FaultException<ValidationFault>)
{
throw;
}
我可以检查BLL中的异常并确认它是一个强类型的FaultException,并且从DAL传递的Detail部分完好无损。尝试重新抛出异常的BLL方法使用与上面DAL方法相同的[FaultContract]属性进行修饰。
UI客户端是BLL服务的客户端,它尝试处理异常并记录/显示相应的信息。麻烦的是,当这个错误到达客户端时,它不再是一个强类型的FaultException,而是一个带有null Detail部分的一般FaultException。
我确实发现如果不是仅仅重新抛出BLL方法中的错误,而是使用相同的参数重新创建它:
catch (FaultException<ValidationFault> valEx)
{
throw new FaultException<ValidationFault>(new ValidationFault(valEx.Detail.Message, valEx.Detail.PropertyName));
}
然后它按预期的方式作为强类型的FaultException到达客户端。
我的问题是:为什么我需要在BLL服务中重新创建此异常?为什么我不能直接通过DAL服务抛出的强类型FaultException?我得到了代码,但想了解发生了什么。我想这是一种让我盯着我的东西,但我不能为我的生活弄明白。
答案 0 :(得分:2)
确实答案一直盯着我,所以如果这有助于某人在路上:我的问题是FaultContract的Action属性。使用FaultContract属性修饰操作时,除非明确指定Action,否则WCF会自动为您生成操作。此Action包括FaultException命名空间,以及生成故障的操作的服务和方法名称。在我的例子中,我的BLL层中的服务和方法名称与最初生成异常的DAL方法的服务和方法名称不同,所以尽管我的DAL和我的BLL层操作都使用相同的属性进行了装饰:
[FaultContract(typeof(ValidationFault))]
...... FaultContract的行动是不同的。因此,当尝试在BLL服务中重新抛出DAL FaultException时,FaultContract与BLL操作上指定的不匹配,并且WCF将异常重新打包为一般的FaultException,而不是强类型的。
我在这种情况下的选择是在我的BLL服务中重新创建FaultException,这会创建正确的Action,但是当它到达我的客户端时,它似乎来自BLL服务;除非我明确指定它,否则它会在DAL中丢失,或者将Action属性添加到BLL操作的FaultContract属性,并指定DAL生成的错误的Action。关于哪个是更好的想法和更好的实践,这可能是另一个主题,但我现在已经了解了正在发生的事情,这就是我所追求的。