Igor Entaltsev
Igor Entaltsev

Reputation: 67

ASP.NET MVC4 entity validation errors: User name already taken

I am new to ASP.NET MVC4, getting a validation error on the code below.

My app is using Identity and a Database.

I have some tables populated with some testing data. A call to dc.SaveChanges() returns Validation errors.

I created the following classes: Faculty deriving from class Person deriving from class IdentityUser.

I created a role named Faculty, then created a Faculty object named mark and added it the Faculty role. As mark logs in and the Database starts initializing, I get the error "User name Peter is already taken."

An explanation would be greatly appreciated.

Code

Class Person:

public class Faculty : Person {
    public Faculty() {
        this.Courses = new List<Course>();
        SenecaId = string.Empty;
    }
    public Faculty(string fname, string lname, string phone, string senId)
        : base(fname, lname, phone) {
        this.Courses = new List<Course>();
        this.Messages = new List<Message>();
        SenecaId = senId;
    }
    [Required]
    [RegularExpression("^[0][0-9]{8}$", ErrorMessage = "0 followed by 8 digits")]
    public string SenecaId { get; set; }
    public List<Course> Courses { get; set; }
    public List<Message> Messages { get; set; }
}

Class IdentityUser:

public class Person : IdentityUser {
    public Person() {
      FirstName = LastName = Phone = string.Empty;
    }
    public Person(string f, string l, string p) {
      FirstName = f;
      LastName = l;
      Phone = p;
    }
    [Key]
    public int PersonId { get; set; }
    [Required]
    [StringLength(40, MinimumLength = 3)]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }
    [Required]
    [StringLength(100, MinimumLength = 3)]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    [Required]
    [RegularExpression("^[2-9]\\d{2}-\\d{3}-\\d{4}$", ErrorMessage = "nnn-nnn-nnnn")]
    public string Phone { get; set; }
}

Role Faculty:

string roleFaculty = "Faculty";
if (!RoleManager.RoleExists(roleFaculty)) {
    var roleFacultyCreateResult = RoleManager.Create(new IdentityRole(roleFaculty));
}

Creating Faculty object (Mark) and adding it to role Faculty:

// 1 create faculty Mark (8)
Faculty mark = new Faculty();
// add "mark" to role "faculty"
mark.SenecaId = "034234678";
mark.FirstName = "Mark";
mark.LastName = "McTest";
mark.Phone = "555-567-6789";
mark.UserName = "Mark";

string UserMarkPw = "123456";
var UserMarkCreate = UserManager.Create(mark, UserMarkPw);
if (UserMarkCreate.Succeeded) {
    var addUserMarkToRoleFacultyResult = UserManager.AddToRole(mark.Id, roleFaculty);
}
mark.HomeTown = "Markham";
var UserMarkInfo = new MyUserInfo() { 
    FirstName = "Mark", LastName = "McTest" };
mark.MyUserInfo = UserMarkInfo;
mark.PersonId = 8;
dc.Faculties.Add(mark);  

The error:

"Entity of type Faculty in state Added has the following validation errors:"
...
"User name Peter is already taken."

Upvotes: 2

Views: 4294

Answers (2)

Pabitra Dash
Pabitra Dash

Reputation: 1513

You may be getting error "User name Mark is already taken." Because user with UserName 'Mark' is created and saved in DB with following statement.

var UserMarkCreate = UserManager.Create(mark, UserMarkPw);

Again you are trying to add 'Mark' in dc with statement dc.Faculties.Add(mark);

Now when you do dc.SaveChanges(), it again tries to insert 'Mark' in DB. Hence you are getting error,

"User name Mark is already taken."

Upvotes: 1

Chris Pratt
Chris Pratt

Reputation: 239440

You've already bound them. That's your problem. IdentityUser is the user account, since Faculty is a Person is a IdentityUser, Faculty is a IdentityUser. By creating the Faculty object, you created a user account as well.

In fact, unless you customized the entity configuration, Entity Framework did all this in the AspNetUsers table with a discriminator column. In other words, you don't have an actual Faculty table or a Persons table, but one AspNetUsers table with a column filled the name of the specific class type ("Faculty", "Person", etc.).

UPDATE

Identity only supports one user type. You specify what type that will be with the IdentityDbContext<> generic you inherit from in your application's context. In your case, you've set that to Person (i.e. IndentityDbContext<Person>). That means, ApplicationUser is not utilized at all. That's fine if that's what you want. Your "user" can be named whatever you like; it doesn't have to be ApplicationUser. Then, you've merely employed STI (single-table inheritance) to add a more specific "type" of user, which would be your Faculty class. Entity Framework does this by default for inheritance stuctures where a base class is an entity (mapped to a database table). Basically all the fields for Faculty, Person and IdentityUser are all mapped to the same database table, and a discriminator column is added to track the specific class type that Entity Framework should instantiate when that row is pulled from the database. STI is a common inheritance strategy for mapping object hierarchies to a relational database, and for the most part it works well, but you need to keep in mind that all fields on superclasses must be nullable. In other words, you cannot have a field on Faculty that is NOT NULL at the database level, or you'll get an error. You can, however, make the field required through your application, even though it is technically not required at the database level to insert a new row.

Upvotes: 1

Related Questions