2

我有用户创建的页面,显然我不希望我的用户拥有相同的用户名,所以我为此创建了验证,但是我现在编辑用户时遇到问题。当我尝试编辑用户时,它不允许我这样做,因为它说用户名已经被占用。但我什至不想编辑用户名,只是密码什么的。

编辑:我确实通过调用犯了错误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 上(因为你不能更改你的用户名)

4

3 回答 3

3

您的编辑方法加载User具有用户名的实体。之后,您调用ValidateModel它检查User数据库中是否存在具有此用户名的 a,如果存在则返回 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");
    }
}
于 2012-11-01T15:46:50.283 回答
0

您获得的异常是由于在属性“ProxyCreationEnabled”设置为 true 的情况下创建了 EF 上下文。试试这个,而不是“context.ContextOptions.ProxyCreationEnabled = false;”

但是,就您的验证而言,我将摆脱数据注释,而是使用更容易使用和编写测试的流畅验证。

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

于 2012-11-01T15:51:30.317 回答
0

我不确定你在这里做什么,因为你正在验证你刚刚从数据库中提取的模型,那应该还没有被验证吗?

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

if(ModelState.IsValid)

如果这没有验证,那么您可以在这种情况下使用 *username 删除特定的属性验证错误):

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

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

于 2012-11-01T15:46:40.133 回答