Search code examples
c#asp.net-mvcentity-frameworkvalidationvalidationattribute

How To Disable or Change Attribute According to CRUD Operation Insert Or Update


I'm trying to build a small website using ASP.NET MVC With EntityFramework on Visual Studio 2013.4

I have this model:

    public Class User
    {
Public int UserID {get;set;}
        [Required]
        [ValidUserName]

        public string UserName { get; set; }

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

    }

This model has a Custom Attribute which is called [ValidUserName].

public class ValidUserName : ValidationAttribute
{
    PMAIDEntities db;
    public ValidUserName()
    {
        db = new PMAIDEntities();
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {

            var valueAsString = value.ToString();
            bool IsExist = db.Users.Where(x => x.UserName == (string)value).Any();
            if (IsExist)
            {
                var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                return new ValidationResult("User Name is Already Exist !!");
            }                   
        }
        return ValidationResult.Success;
    }
}

The problem is when I try to add a new record to the database the [ValidUserName] works fine, which informs the end-user if the username exists in the database or not. But, when the update operation occur on a record to change password the [ValidUserName] gives me that the username exists in the database. enter image description here

I know that the username already exists, but how can I solve this problem to let [ValidUserName] accept current username because the username shall remain as is?

This the the code in the controller:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "UserID,UserName,UserPassword,UserRole,UserFullName,UserEmail,UserMobile,UserLastLogin,UserAddress,UserBio,UserNationality,UserGender,UserDOB,UserAge,UserDateAdded")] User user)
{
    if (ModelState.IsValid)
    {
        db.Entry(user).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.UserNationality = new SelectList(db.Nationalities, "Id", "Name", user.UserNationality);
    return View(user);
}

edit

i use this code in model

    public class User
    { 

        public int UserID { get; set; }

    [Required]
    [Remote("IsUserNameValid", "Users", AdditionalFields = "UserID", ErrorMessage = "Username already exists.")]
        [ValidUserName]
        public string UserName { get; set; }

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

and in the controller i add the following code

public JsonResult IsUsernameValid(string UserName, int UserID)
{
    var isValid = true;

    if (UserName != null)
    {
        isValid = !db.Users.Where(x => x.UserName == UserName && x.UserID != UserID).Any();
    }

    return Json(isValid, JsonRequestBehavior.AllowGet);
}

the problem here is the remote attribute require to specify the controller name , in this case what should i write if is my controller located inside an area called 'Admin'


Solution

  • You need to use Remote Validation (RemoteAttribute). Add this action method to your controller (I'm assuming your UserID is integer):

    public JsonResult IsUserNameValid(string UserName, int UserID = 0)
    {
        var isValid = true; 
    
        if (UserName != null)
        {
            isValid = !db.Users.Where(x => x.UserName == UserName && x.UserID != UserID).Any();                         
        }
    
        return Json(isValid, JsonRequestBehavior.AllowGet);
    }
    

    Then, use it in your model like this (updated for calling the controller in the Admin area):

    public class User
    {
        [Required]
        [Remote("IsUserNameValid", "Users", "Admin", 
           AdditionalFields = "UserID", ErrorMessage = "Username already exists.")]
        public string UserName { get; set; }
    
        [Required]
        public string UserPassword { get; set; }
    
        // other properties...
    }
    

    You can read more about implementing Remote Validation in asp.net MVC here.