如何将验证错误从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);
    }
}

如何将验证错误从EntityFramework传递到WCF

最简单的方法是捕获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);
        }
    }
}

您可能还想复制DbEntityValidationExceptionEntityValidationErrors列表中的DbEntityValidationResult数据。在这种情况下,您必须使用字段PropertyNameErrorMessage定义另一个数据契约,并且您必须编写一些代码来复制每个错误消息。

当然,令人讨厌的是,您必须为每个服务操作编写相同的包装器代码。您很快就会发现,您需要将包装器代码移动到辅助类中,但每次都需要编写try-catch代码。在我工作的地方,我们使用PostSharp的面向方面编程,以通用的方式解决了这个和类似的问题。我们制作了一个名为ValidationFaultAspect的方面,当异常应用于方法时,它会自动转换异常。我认为用PostSharp的免费版本可以做到这一点,但我不能100%确定。