如何将验证错误从EntityFramework传递到WCF
本文关键字:WCF EntityFramework 验证 错误 | 更新日期: 2023-09-27 18:28:40
我读过很多关于它的文章,似乎都是非常复杂的解决方案。但我相信应该有一个简单的方法来解决我的问题。
我已经用属性对我的对象进行了实体框架验证,该属性从资源中返回错误消息(但这无关紧要,就像ErrorMessage=…一样)
[MetadataType(typeof(UserMetadata))]
public partial class User
{
internal sealed class UserMetadata
{
[Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserNameRequired", ErrorMessageResourceType = typeof(ErrorMessage))]
[StringLength(150, ErrorMessageResourceName = "UserNameLength", ErrorMessageResourceType = typeof(ErrorMessage))]
public string UserName { get; set; }
}
}
在我的WCF服务中,我有一个合同:
[ServiceContract]
public interface IUser
{
[OperationContract]
User AddUser(User user);
}
以及实现:
public class UserService: IUser
{
public User AddUser(User user)
{
//Here I think I should throw the ErrorMessage with a FaultException
//and to catch it in the client side, but how to do it !?
IUserRepository _user = new UserRepository(); //I've used EF Repository Pattern.
return _user.Add(user);
}
}
最简单的方法是捕获DbEntityValidationException
并将其转换为所需类型的FaultException
。我将描述一个简单的版本。首先创建自定义故障:
[DataContract]
public class ValidationFault
{
}
修改服务契约以指示可能引发故障:
[ServiceContract]
public interface IUser
{
[OperationContract]
[FaultContract(typeof(ValidationFault))]
User AddUser(User user);
}
并修改服务代码以转换异常:
public class UserService: IUser
{
public User AddUser(User user)
{
try
{
IUserRepository _user = new UserRepository(); //I've used EF Repository Pattern.
return _user.Add(user);
}
catch (DbEntityValidationException ex)
{
throw new FaultException<ValidationFault>(new ValidationFault(), ex.Message);
}
}
}
您可能还想复制DbEntityValidationException
上EntityValidationErrors
列表中的DbEntityValidationResult
数据。在这种情况下,您必须使用字段PropertyName
和ErrorMessage
定义另一个数据契约,并且您必须编写一些代码来复制每个错误消息。
当然,令人讨厌的是,您必须为每个服务操作编写相同的包装器代码。您很快就会发现,您需要将包装器代码移动到辅助类中,但每次都需要编写try-catch代码。在我工作的地方,我们使用PostSharp的面向方面编程,以通用的方式解决了这个和类似的问题。我们制作了一个名为ValidationFaultAspect
的方面,当异常应用于方法时,它会自动转换异常。我认为用PostSharp的免费版本可以做到这一点,但我不能100%确定。