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

时间:2013-08-22 10:11:12

标签: c# wcf validation entity-framework-5 faultexception

我读过很多关于它的文章,而且似乎都是非常复杂的解决方案。 但我相信应该有一个简单的方法来解决我的问题。

我已经使用Attributes为我的对象进行了实体框架验证,这些资源从资源返回错误消息(但是它与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);
    }
}

1 个答案:

答案 0 :(得分:2)

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

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

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