1

一意のユーザー名の検証を作成しましたが、ユーザーを編集できません。ユーザー名は既に使用されていると言っていますが、編集しようとしているユーザーが使用しているため、これは理にかなっています。ユーザー名を編集したくありませんが、このエラーのために他のフィールドも編集できません。

EDIT アクションの一意のユーザー名の検証を無効にするにはどうすればよいですか?

バリデーター

public override bool IsValid(object value)
{
    if (value == null) return false;
    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;
}

アクション

[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 values and save changes
    user.Address = u.Address;
    if (!string.IsNullOrEmpty(u.Password)) user.Password = Infrastructure.Encryption.SHA256(u.Password);
    _db.SaveChanges(); // validation error

    return null;
}

モデル

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

    [Required]
    [UniqueUsername(ErrorMessage = "Username is already taken")]
    public string Username { get; set; }

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

    public string Address { get; set; }
}

エラー

1 つ以上のエンティティの検証に失敗しました。詳細については、「EntityValidationErrors」プロパティを参照してください。

4

4 に答える 4

2

UniqueUsername 属性の「AdditionalFields」パラメーターに「ID」プロパティを渡すので、コードは次のようになるはずです

クラス プロパティ:

[Required]
[UniqueUsername(ErrorMessage = "Username is already taken", AdditionalFields = "ID")]
public string Username { get; set; }

検証アクション:

public ActionResult UniqueUsername(string userName, int id)
{
    FinanceDataContext _db = new FinanceDataContext();
    var user = _db.Users.ToList().SingleOrDefault(x => x.Username.ToLower() == value.ToString().ToLower() && x.ID != id);
    return Json(user == null, JsonRequestBehavior.AllowGet);
}

これが役立つことを願っています!!

于 2012-11-01T17:44:05.883 に答える
1

貢献したいことが一つ。

このコード:

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

ToList()実行するとクエリ全体が実行されるため、パフォーマンスは高くありません。この場合、データベースからすべてのユーザーを取得し、メモリ内でフィルターを実行しています。

これを行うことをお勧めします:

_db.Users.Where(x => x.Username.ToLower() == value.ToString().ToLower()).SingleOrDefault();

ToList()1 つのレコードを取得するだけなので、メソッドを呼び出す必要はありません。最後だけSingleOrDefault()で十分です。

于 2012-11-01T17:55:12.320 に答える
1

ユーザー ID を IsValid メソッドに渡して、返されたユーザーが同じユーザー ID を持っていないことを確認できますか?

于 2012-11-01T17:35:49.413 に答える
0

オブジェクト全体をバリデーターに渡し、ID とユーザー名をチェックすることで修正しました。

public override bool IsValid(object value)
{
    var user = (User)value;
    if (user == null) return true;

    FinanceDataContext _db = new FinanceDataContext();
    var u = _db.Users.Where(x => x.Username.ToLower() == user.Username.ToLower() && x.ID != user.ID).SingleOrDefault();
    if (u == null) return true;
    return false;
}
于 2012-11-01T18:09:13.223 に答える