How to create custom additional fields in UserProfile in MVC4

testCoder picture testCoder · Sep 15, 2012 · Viewed 48.8k times · Source

I faced with new ASP MVC 4 feature, it shipped with new membership db schema and new initialization. In mvc 3 and old versions developer able to create custom user profile fields using specifications in web.config, but now i faced with method in filters namespace in default mvc 4 project:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

and user profile table:

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

But the method InitializeDatabaseConnection generate only UserName and UserId i need to generate other additional fields.

I have good experience in EF codeFirst approach, and in that case i try to edit UserProfile Class:

[Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        [Column]
        [Required]
        public string UserName { get; set; }
        [Column]
        [Required]
        public string FirstName { get; set; }
        [Column]
        [Required]
        public string LastName { get; set; }
    }

But when i regenerate database, i havent see any changes, Custom Db fields not generated. Help me please, how can i create custom user fields?

Answer

IMLiviu picture IMLiviu · Sep 17, 2012

Elaborating from the answer above

The WebSecurity.InitializeDatabaseConnection Method help states that

If you want to use a database table that contains user profile information (user names, email addresses, and so on), you specify a connection string and table name that the membership system uses to connect to that information. If you do not want to use an existing user profile table, you can specify that the InitializeDatabaseConnection() method should automatically create the user profile table. (A database for the user profile table must already exist.)

So if we want more fields into the UserProfile table we just need to make sure we are creating a profile table and run the InitializeDatabaseConnection method after the table is already in place.

In the standard MVC4.0 project template from VS2012 I've commented out the Account controller

[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
{

and moved InitializeDatabaseConnection into the EF Code First Database Initializer

public class MyDatabaseInit: DropCreateDatabaseAlways<MyDatabaseContext>
{
    protected override void Seed(MyDatabaseContext context)
    {
        SeedMembership();
    }

    private void SeedMembership()
    {
        WebSecurity.InitializeDatabaseConnection("MyDatabaseContext",
            "UserProfile", "UserId", "UserName", autoCreateTables: true);
    } 
}

ensuring that the InitializeDatabaseConnection runs once the table is already in place.

Added the UserProfile class to my EF Code First model

public class MyDatabaseContext : DbContext
{
    public DbSet<UserProfile> UserProfiles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Added the extra field in the UserProfile table

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

All you need now is to set the database initialization strategy when the application starts and also call a query on the database the make sure it gets created at that point, before any authorization/authentication code is called.

protected void Application_Start()
{
   AreaRegistration.RegisterAllAreas();

   WebApiConfig.Register(GlobalConfiguration.Configuration);
   FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
   RouteConfig.RegisterRoutes(RouteTable.Routes);
   BundleConfig.RegisterBundles(BundleTable.Bundles);
   AuthConfig.RegisterAuth();

   Database.SetInitializer<MyDatabaseContext>(new MyDatabaseInit());
   new MyDatabaseContext().UserProfile.Find(1);
}