Customizing SimpleMembership

asp.net-mvc-4, c#, entity-framework-5, simplemembership

Solution

I struggled a lot with the same issue. The key is to get the relation between the UserProfile class and your Student class correct. It have to be a one-to-one relationship in order to work correct.

Here is my solution:

Person.cs

public class Person
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    /* and more fields here */

    public virtual UserProfile UserProfile { get; set; }
}

UserProfile.cs

public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }

    public virtual Person Person { get; set; }
}

MyDbContext.cs

public class MyDbContext : DbContext
{
    public DbSet<Person> Person { get; set; }
    public DbSet<UserProfile> UserProfile { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
     modelBuilder.Entity<UserProfile>()
                    .HasRequired(u => u.Person)
                    .WithOptional(p => p.UserProfile)
                    .Map(m => m.MapKey("PersonId"));
    }
}

However, I also struggled with creating users with the WebSecurity.CreateUserAndAccount method. So I ended up creating my Person objects with Entity Framework and then create the user account with the membership provider method:

AccountRepository.cs

 public Person CreatePerson(string name, string username) {

     Person person = new Person { Name = name };
     _dbContext.Person.add(person);
     _dbContext.SaveChanges();

     var membership = (SimpleMembershipProvider)Membership.Provider;
     membership.CreateUserAndAccount(
         model.UserName, 
         createRandomPassword(), 
         new Dictionary<string, object>{ {"PersonId" , person.Id}}
     );

 }

Problem

After reading this good BLOG about adding custom data to UserProfile table, I wanted to change it the way that UserProfile table should store default data + another class where all additional info is stored. After creating new project using Interenet application template, I have created two classes: Student.cs ``` [Table("Student")] public class Student { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public virtual int StudentId { get; set; } public virtual string Name { get; set; } public virtual string Surname { get; set; } public virtual int UserId { get; set; } } ``` UserProfile.cs ``` [Table("UserProfile")] public class UserProfile { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } public virtual int StudentId { get; set; } public virtual Student Student { get; set; } } ``` also, I've deleted the UserProfile definition from AccountModel.cs. My DB context class looks like this: MvcLoginDb.cs ``` public class MvcLoginDb : DbContext { public MvcLoginDb() : base("DefaultConnection") { } public DbSet<UserProfile> UserProfiles { get; set; } public DbSet<Student> Students { get; set; } } ``` again, I have deleted db context definition from AccountModel.cs. Inside Package-Manager-Console I've written: ``` Enable-Migrations ``` and my Configuration.cs looks like this: ``` internal sealed class Configuration : DbMigrationsConfiguration<MvcLogin.Models.MvcLoginDb> { public Configuration() { AutomaticMigrationsEnabled = true; } protected override void Seed(MvcLogin.Models.MvcLoginDb context) { WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); if (!WebSecurity.UserExists("banana")) WebSecurity.CreateUserAndAccount( "banana", "password", new { Student = new Student { Name = "Asdf", Surname = "Ggjk" } }); } } ``` That was the idea of adding student data as creating a new class, but this approach is not working because after running Update-Database -Verbose I'm getting the error: No mapping exists from object type MvcLogin.Models.Student to a known managed provider native type. Can anyone expain why I'm getting this error, shoud I use a different approach for storing additional data in different table?

Original source