错误:一个或多个实体的验证失败(C#.Net后端)

时间:2018-02-01 15:16:40

标签: c# entity-framework azure

我知道StackOverflow上已经用尽了这个错误,但我真的相信我会处理一种不同的错误。

我正在使用azure移动服务开发Xamarin.iOS应用,因此是Azure .Net后端。

当用户创建新帐户时,我会在数据库中保存新的帐户对象。

这发生在后端,在返回HttpResponseMessage的函数中,返回成功或失败消息。

在保存新帐户详细信息的同时,我还会生成 salt 哈希密码。我保存了盐和哈希密码。

错误发生在SaveChanges()上,但我注意到数据库中的salt为空。

[MobileAppController]
[RoutePrefix("api/register")]
[AllowAnonymous]
public class RegisterController : ApiController
{

    [HttpPost]
    [Route("newuser")]
    public HttpResponseMessage NewUser(RegistrationRequest request)
    {
        try
        {

            //...... code truncated for brevity

            myContext context = new myContext();
            DataObjects.Account account = context.Accounts.Where(a => a.Username == request.username).SingleOrDefault();

            if (account != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, new
                {
                    message = "That username already exists",
                    error = true
                });

            }
            else
            {
                    byte[] salt = CustomLoginProviderUtils.generateSalt();

                    DataObjects.Account newAccount = new DataObjects.Account()
                    {
                        Id = Guid.NewGuid().ToString(),
                        Username = request.username,
                        Salt = salt,
                        CreatedAt = DateTime.UtcNow,
                        SaltedAndHashedPassword = CustomLoginProviderUtils.hash(request.password, salt)
                    };
                    context.Accounts.Add(newAccount);
                    context.SaveChanges();

                return Request.CreateResponse(HttpStatusCode.OK, new
                {
                    message = "Account created successfully!",
                    error = false,
                    account = newAccount
                });
        }


        }catch(Exception ex)
        {
            // Retrieve the error messages as a list of strings.
            //var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);

            //// Join the list to a single string.
            //var fullErrorMessage = string.Join(";", errorMessages);

            //// Combine the original exception message with the new one.
            //var exceptionMessage = string.Concat(ex.Message, "The validation errors are:", fullErrorMessage);

            // Throw a new DbEntityValidationException with the improved exception message.
            //throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);

            return Request.CreateResponse(HttpStatusCode.OK, new
            {
                message = "Failed!",
                error = true
            });            
        }

从上面的代码中可以看出,经过这里的大量研究后,我遇到了一个解决方案,打印出DbEntityValidationException中的所有错误。

我有3个挑战:

  1. 我意识到错误没有引发异常,并且始终返回HttpResponseMessage
  2. {{message: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details, error: true}}

    这使我更难确定哪些列确实失败了。

    我甚至尝试覆盖SaveChanges()类中的DbContext函数并在异常中实现了上述功能,但它从不引发异常。再说一遍,我不确定是什么失败了。

    public override int SaveChanges()
        {
    
            try
            {
                return base.SaveChanges();
    
            }catch (DbEntityValidationException ex)
            {
                // Retrieve the error messages as a list of strings.
                var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);
    
                // Join the list to a single string.
                var fullErrorMessage = string.Join(";", errorMessages);
    
                // Combine the original exception message with the new one.
                var exceptionMessage = string.Concat(ex.Message, "The validation errors are:", fullErrorMessage);
    
                // Throw a new DbEntityValidationException with the improved exception message.
                throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
            }
        }
    

    我怀疑salt值是导致错误的原因,但我已经为salt列提供了一个NULL值,该值在我的数据库中是varbinary(Max)数据类型。所以空值不应该是一个问题。

    2. **挑战号2是我在客户端测试了盐生成,我可以看到生成的值不为空。

    所以我不确定为什么它没有保存到数据库中。**

    **Generate Salt function**
    
     public static byte[] generateSalt()
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] salt = new byte[256];
            rng.GetBytes(salt);
            //rng.GetNonZeroBytes(salt);
            return salt;
        }
    

    第3。最后的挑战是我不确定从何处返回HttpResponseMessage。

    我将错误设置为true的唯一位置是找到现有帐户时以及此NewUser函数的例外情况。我知道它不是来自异常,因为无论我在响应中更改message多少次以及错误属性值,结果总是相同的 - 验证失败错误消息。

    请帮助我找出导致此错误的原因。感谢。

    修改

    帐户类架构

        public class Account : EntityData
         {
            public string Username { get; set; }
            public byte[] Salt { get; set; }
            public byte[] SaltedAndHashedPassword { get; set; }
    
         }
    
    [![Accounts Table Schema][1]][1]
    

0 个答案:

没有答案