0

New to MVC. When I try to add a user to the database using Entity Framework Database First I get this exception:

An exception of type 'System.Data.Entity.Validation.DbEntityValidationException' occurred in EntityFramework.dll but was not handled in user code

Additional information: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

This is the code:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(RegisterViewModel account)
    {
        if (ModelState.IsValid)
        {
            using (db)
            {
                bool duplicate = db.Users.Any(a => a.UserName == account.UserName);

                if (duplicate)
                {
                    ModelState.AddModelError("", "Username already exists in database!");
                }
                else
                {
                    db.Users.Add(new StoreFront.Models.User { UserName = account.UserName, Password = account.Password, EmailAddress = account.EmailAddress, IsAdmin = false, DateCreated = DateTime.Now });
                    db.SaveChanges();

                    ModelState.Clear();

                    ModelState.AddModelError("RegisterSuccess", "Successfully registered!");
                }
            }
        }
        return View();
    }

I have validation in my RegisterViewModel for all fields, and when I debug, IsValid = true, otherwise it wouldn't run anyway. Any help would be greatly appreciated...I have been struggling with this for a while.

P.S. Yes the password is currently being stored as a string, this is just a test project that won't be used in the real world.

EDIT: Added Models:

User Model from database:

 public partial class User
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public User()
        {
            this.Addresses = new HashSet<Address>();
            this.Orders = new HashSet<Order>();
            this.ShoppingCarts = new HashSet<ShoppingCart>();
        }

        public int UserID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string EmailAddress { get; set; }
        public Nullable<bool> IsAdmin { get; set; }
        public Nullable<System.DateTime> DateCreated { get; set; }
        public string CreatedBy { get; set; }
        public Nullable<System.DateTime> DateModified { get; set; }
        public string ModifiedBy { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Address> Addresses { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Order> Orders { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<ShoppingCart> ShoppingCarts { get; set; }
    }

Partial Model to add ConfirmPassword:

namespace StoreFront.Models
{
    [MetadataType(typeof(RegisterViewModel))]
    public partial class User
    {
        [DisplayName("Confirm Password")]
        [DataType(DataType.Password)]
        [Compare("Password", ErrorMessage = "Passwords must match")]
        public string ConfirmPassword { get; set; }
    }
}

RegisterViewModel:

public class RegisterViewModel
    {
        public int UserID { get; set; }

        [DisplayName("Username")]
        [Required(ErrorMessage = "Username is required")]
        public string UserName { get; set; }

        [DisplayName("Password")]
        [DataType(DataType.Password)]
        [Required(ErrorMessage = "Password is required")]
        public string Password { get; set; }

        [DisplayName("Confirm Password")]
        [DataType(DataType.Password)]
        [Compare("Password", ErrorMessage = "Passwords must match")]
        public string ConfirmPassword { get; set; }

        [DisplayName("Email")]
        [Required(ErrorMessage = "Email is required")]
        [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$",
        ErrorMessage = "Please enter a valid email")]
        public string EmailAddress { get; set; }

        public Nullable<bool> IsAdmin { get; set; }
        public Nullable<System.DateTime> DateCreated { get; set; }
    }
bankey
  • 189
  • 12
  • 2
    First of all you should `See EntityValidationErrors property for more details` – Szer Jun 20 '16 at 12:34
  • `ModelState.IsValid` indicates that data in `RegisterViewModel` is valid. But doesn't indicate that data in your `User` entity is valid. – haim770 Jun 20 '16 at 12:36
  • Normally this error will relate to your model field not inserted properly.I suggest you look into [this](http://stackoverflow.com/questions/7795300/validation-failed-for-one-or-more-entities-see-entityvalidationerrors-propert).Basically you do a `try-catch` and the error message will be displayed indicating what is the problem that prevent you from inserting to db. – Shawn Yan Jun 20 '16 at 12:38
  • I saw that question earlier, and tried doing the answer about the watch, but I will try using a try-catch and see how it works – bankey Jun 20 '16 at 12:39
  • When I use the try catch block at stated in that post, it gives me the same exception on the line with `throw;` and if I remove that line it skips over `db.SaveChanges();` and says successfully registered without adding to db – bankey Jun 20 '16 at 12:44
  • Try expanding the exception and see the inner messages. – Shawn Yan Jun 20 '16 at 12:51
  • Not sure what to look for in watch window, but I found "The name 'SaveChanges' does not exist in the current context. Also `+ OriginalValues 'new System.Collections.Generic.Mscorlib_CollectionDebugView(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors).Items[0].Entry.OriginalValues' threw an exception of type 'System.InvalidOperationException' System.Data.Entity.Infrastructure.DbPropertyValues {System.InvalidOperationException} ` – bankey Jun 20 '16 at 13:01
  • 1
    1. Make sure your catch looks like this `catch (System.Data.Entity.Validation.DbEntityValidationException ex) {/* logging and then throw */ }`. 2. Put a break point in the catch. 3. Inspect object `ex`. 4. Inspect property `EntityValidationErrors` of object `ex` – Igor Jun 20 '16 at 13:03
  • The internal error message when I use the first try catch from Shawn Yan's hyperlink is the confirm password (passwords must match), which shouldn't be used anyway. I added `ConfirmPassword = null` to the `db.Add` line and it still gives the same error, on the `throw;` ... – bankey Jun 20 '16 at 13:12
  • Kindly check whether your data annotations on ConfirmPassword property doesn't perform any kind of validations. E.g. `[System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]` – Shawn Yan Jun 20 '16 at 15:06
  • There are indeed validations for both Password and ConfirmPassword. What happens during the `db.Add` is that `IsValid` becomes false...and I don't understand why, nor if that is what is throwing the error – bankey Jun 20 '16 at 15:59
  • share your model here – Anshul Nigam Jun 21 '16 at 04:44
  • @AnshulNigam added – bankey Jun 21 '16 at 11:52
  • @bankey were you able to check your Entity Validation Errors in the catchh block? – Grizzly Jun 21 '16 at 12:14
  • When I create a catch block, I still get the same error on `throw;`...I have been trying to use the Watch window, but honestly I don't know how to navigate through it – bankey Jun 21 '16 at 13:09
  • When I go to the QuickWatch and paste `((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage` it gives me "Passwords must match" as the value. I don't know if that helps, but I believe it has something to do with the confirm password field, either the field itself or the validation... – bankey Jun 22 '16 at 15:51
  • Don't want to bring up a day or two old post but I know it's something small, and I would love to fix it – bankey Jun 23 '16 at 11:58

2 Answers2

0

Fix: When I looked up a tutorial about MVC it asked em to create a partial class and a meta class. That was for code first I believe, which basically made it a new field that my database didn't have a spot for, and I am using database first. So I removed the deleted the partial class for User and it stopped making ConfirmPassword an actual field in the database.

Don't know the real works of it, or if what I said makes sense, but I hope this helps someone eventually.

bankey
  • 189
  • 12
0

Remove

[RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$",
ErrorMessage = "Please enter a valid email")]

from RegisterViewModel

FelixSFD
  • 6,052
  • 10
  • 43
  • 117
TsiamKav
  • 1
  • 1