无法更新用户,因为它正在检查唯一的用户名

时间:2012-11-01 15:38:47

标签: c# asp.net asp.net-mvc asp.net-mvc-4

我有用户创建的页面,显然我不希望我的用户拥有相同的用户名,所以我创建了我的验证,但是我现在有问题编辑用户。当我尝试编辑用户时,它不允许我这样做,因为它表示已经使用了用户名。但我甚至不想编辑用户名,只是密码或其他东西。

编辑:我通过调用ValidateModel()确实犯了错误,现在我修复了这个问题,但仍然遇到了问题。

验证

public class UniqueUsername : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null) return true; // In Edit view you can't edit username so it's null

        FinanceDataContext _db = new FinanceDataContext();
        var user = _db.Users.ToList().Where(x => x.Username.ToLower() == value.ToString().ToLower()).SingleOrDefault();

        if (user == null) return true;
        return false;
    }
}

模型

public class User
{
    public int ID { get; set; }

    // When I remove UniqueUsername and Remote validators everything works just fine
    [Required]
    [UniqueUsername(ErrorMessage = "Username is already taken")]
    [Remote("CheckUsername", "User", null, ErrorMessage = "Username is allready taken", HttpMethod = "POST")]
    public string Username { get; set; }

    [Required]
    public string Password { get; set;}
}

动作

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(User u)
{
    // Get user we want to edit
    var user = _db.Users.Where(x => x.ID == u.ID).SingleOrDefault();
    if (user == null) return HttpNotFound();

    // Set new fields manually
    if (!string.IsNullOrEmpty(u.Password)) user.Password = Infrastructure.Encryption.SHA256(u.Password);

    ModelState.Remove("Username"); // this doesen't seem to do much...

    _db.SaveChanges(); // validation error here
    return Content(Infrastructure.Helper.SerializeObject(u));
}

错误

  

一个或多个实体的验证失败。看到   'EntityValidationErrors'属性以获取更多详细信息。

我知道为什么它会让我失误。因为他检查用户名是否已被占用,当然已经采取了,但我想验证用户名是否仅在CREATE上获取,而不是在EDIT上(因为您无法更改用户名)

3 个答案:

答案 0 :(得分:3)

您的编辑方法会加载具有用户名的User实体。之后你调用ValidateModel来检查数据库中是否有User用户名,如果是,则返回false(无效)。嗯,当然有一个,因为你刚加载它!该错误表明您的IsValid方法返回false。

您的问题的解决方案是检查用户名是否已存在但ID是否不同。将验证更改为此代码:

public class UniqueUsername : ValidationAttribute
{
    public override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) return ValidationResult.Success; // In Edit view you can't edit username so it's null
        var currentUser = validationContext.ObjectInstance as User;
        FinanceDataContext _db = new FinanceDataContext();
        var user = _db.Users.ToList().Where(x => x.Username.ToLower() == value.ToString().ToLower() && x.ID != currentUser.ID).SingleOrDefault();

        if (user == null) return ValidationResult.Success;
        return new ValidationResult("Username exists");
    }
}

答案 1 :(得分:0)

我不确定你在这里做了什么,因为你正在验证刚从数据库中取出的模型,是否已经验证过了?

发布的用户模型(u)在发布时已经过验证,您可以通过以下方式验证其验证:

if(ModelState.IsValid)

如果这不验证,则可以使用*用户名在这种情况下删除特定的属性验证错误):

var username = ModelState["Username"];
if (username != null)
{
   username.Errors.Clear();
}

除非您允许更改用户名,否则这应该没问题;我假设用户名将从经过验证的数据库版本保持不变。

答案 2 :(得分:0)

获取的异常是由于在将“ProxyCreationEnabled”属性设置为true的情况下创建的EF上下文。请尝试使用“context.ContextOptions.ProxyCreationEnabled = false;”

然而,就验证而言,我将放弃数据注释,而是使用更流畅的验证,这更容易使用和编写测试。

http://fluentvalidation.codeplex.com/wikipage?title=mvc&referringTitle=Documentation