我知道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个挑战:
HttpResponseMessage
{{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]