0

Model

public partial class MemberModel 
    {

        [Key]
        public int MemberID { get; set; }

        [Required]
        [Unique_Member]
        [StringLength(255)]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }


        [Required]
        [Unique_Member]
        [StringLength(255)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Display(Name="Name")]
        public string FullName { get { return string.Format(FirstName + " " + LastName); } }

        [Required]
        [StringLength(355)]
        public string Address { get; set; }
        [Required(ErrorMessage="The City field is Required")]
        public int CityID { get; set; }

        [Required(ErrorMessage = "The Country field is Required")]
        public int CountryID { get; set; }


        [Required]
        [RegularExpression(@"^((0092))-{0,1}\d{3}-{0,1}\d{7}$|^\d{4}$|^\d{4}-\d{7}$", ErrorMessage = "Invalid Phone number")]
        [Unique_Member]
        public string Pin { get; set; }


        [Display(Name="Mobile No.")]
        [Required(ErrorMessage="Mobile No. Required")]
        [RegularExpression(@"^((\+92)|(0092))-{0,1}\d{3}-{0,1}\d{7}$|^\d{11}$|^\d{4}-\d{7}$",ErrorMessage="Invalid Phone number")]
        public string Phone { get; set; }


        [Required]
        [EmailAddress]
        public string Email { get; set; }


        public virtual List<Order_SummeryModel> Order_Summeries { get; set; }
        public virtual CountryModel Country { get; set; }
        public virtual CityModel City { get; set; }
    }

Custom Validation [Unique_Member]

its a custom validation for three properties "Pin","FirstName" and "LastName" which i made for create new member. It checks whether fullname and pin of new member is unique or not.

its works perfectly for create action but in edit action this restrict me to update the member model, i want to disable it for edit action, or there is another way to update the model with disable it.

  public class Unique_MemberAttribute : ValidationAttribute
    {
        private static int count;

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Context_getway db = new Context_getway();
            string membervalue = value.ToString();
            //var count = db.Members.Where((x => x.Name == membervalue || x.Pin == membervalue || x.Email == membervalue)).Count();
            var count_fname = db.Members.Where(x => x.FirstName == membervalue).Count();
            var count_lname = db.Members.Where(x => x.LastName == membervalue).Count();
            var count_pin = db.Members.Where(x => x.Pin == membervalue).Count();

            if ((count_fname != 0)||(count_lname != 0))
            {
                count++;
                if (count == 2)
                {
                    return new ValidationResult("Member Already Exist with the same Full Name (Change First Name OR Last Name)!");

                }
            }
            if (count_pin != 0)
            {
                return new ValidationResult("Member Already Exist with the same Pin!");
            }


                return ValidationResult.Success;

        }
    }
    [MetadataType(typeof(MemberModel))]
    public partial class MemberModel
    {

    }

Member Controller (edit action)

 [HttpGet]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            else
            {
                var member = db.Members.Find(id);
                ViewBag.CountryID = new SelectList(db.CountryModels.ToList(), "CountryID", "Country",member.CountryID);
                ViewBag.CityID = new SelectList(db.CityModels.ToList(), "CityID", "City",member.CityID); 
                if (member != null)
                {
                    return View(member);
                }
                else
                    return HttpNotFound();
            }
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(MemberModel member)
        {

            try
            {  
                if (ModelState.IsValid)
                {
                    db.Entry(member).State = System.Data.Entity.EntityState.Modified;
                    db.SaveChanges();
                    TempData["Msg"] = "Update Successfully";
                    return RedirectToAction("Index");
                }
                else
                {
                    ViewBag.CountryID = new SelectList(db.CountryModels.ToList(), "CountryID", "Country",member.CountryID);
                    ViewBag.CityID = new SelectList(db.CityModels.ToList(), "CityID", "City",,member.CityID); 
                    return View(member);
                }
            }
            catch(Exception e)
            {
                TempData["Msg"] = "Update Unsuccessfully: "+ e.Message;
                return View();
            }
        }
Undo
  • 25,519
  • 37
  • 106
  • 129
uri Boyka
  • 1
  • 3

3 Answers3

0

Try this:

ModelState.Remove("PropertyNameInModel");
hakantopuz
  • 481
  • 5
  • 11
  • 'ModelState.Remove("FirstName"); ModelState.Remove("LastName"); ModelState.Remove("Pin");' @codelover I add these three lines in my edit action but its lead me to another error – uri Boyka Dec 25 '16 at 22:01
  • the new error is: **There is no ViewData item of type 'IEnumerable' that has the key 'CityID'.** – uri Boyka Dec 25 '16 at 22:03
0

One way is to remove the error from ModelState in the Edit Controller action, right before checking if the model is valid.

But the better way is to separate your Edit and Insert models.

The Edit Model will have all validation rules for edit; and the Insert model will be inherited from the Edit model and overriding some properties with additional validation rules.

public partial class EditMemberModel 
{

    [Key]
    public int MemberID { get; set; }

    [Required]
    [StringLength(255)]  // Removed the Unique_Member rule**
    [Display(Name = "First Name")]
    public virtual string FirstName { get; set; }

    /// etc.
}


public partial class InsertMemberModel : EditMemberModel
{
    [Required]
    [Unique_Member]
    [StringLength(255)]
    [Display(Name = "First Name")]
    public override string FirstName { get; set; }

    /// etc.
}
Sparrow
  • 2,548
  • 1
  • 24
  • 28
0

You should still do the validation on Edit action method. Otherwise user can edit a record and select a unique combination already used by another record. You should simply use the Id property in your where clause to check any record other than the currently editing record.

So the first step is to get the Id property value of the current entity/view model you are validating. Then use the value in your where clauses.

protected override ValidationResult IsValid(object value, 
                                                  ValidationContext validationContext)
{
    var idProperty = validationContext.ObjectType.GetProperty("MemberID");
    var idValueObj = idProperty.GetValue(validationContext.ObjectInstance, null);
    var id = 0;
    if (idValueObj != null)
        id = (int) idValueObj;

     var db = new Context_getway();
     string membervalue = value.ToString();

    var count_fname = db.Members.Count(x => x.FirstName == membervalue && x.UserId!=id);
    //Your existing code goes here. Make sure to use the id value in your WHERE clauses
}

I just hardcoded the property name ("MemberID") in the answer to give you the idea. But if you want more flexibility, you can pass that when you use the attribute as mentioned in this answer.

Also you should double check your conditions. I find issues with your code. What if the value of your count variable valus is more than 1(ex:2)), then your if (count == 2) will not return true (because your count is more than 2. I am not sure your business requirements/rules. But if you are looking for unique full names, you can create a single LINQ statement to do that ( Use Any method instead of getting Count as needed)

Community
  • 1
  • 1
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thanks for you answer i really appreciate it, you are right that i should also validate member name in edit view but what if member don't want to change his name. – uri Boyka Dec 25 '16 at 22:36
  • Then you still execute your code. But your where clause has now a new thing `(x.UserId!=id)`. This means the code will check whether the name is already being used for another record ( it will exclude the currently editing record). – Shyju Dec 25 '16 at 22:38