How to create custom additional fields in UserProfile in MVC4

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

Accepted Answer

Adding to the response given above

The WebSecurity.InitializeDatabaseConnection According to the method help,

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.)

in order to add additional fields to theUserProfile we only need to confirm that we are building a profile table and execute theInitializeDatabaseConnection technique used once the table has been set up.

I have left the Account controller out of the default MVC4.0 project template from VS2012.

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

and shiftedInitializeDatabaseConnection 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);
    } 
}

making sure that theInitializeDatabaseConnection runs once the table has been set up.

Addition ofUserProfile my EF Code First model with a class

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

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

A new field was added to theUserProfile 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; }
}

To construct the database at that time, before any authorisation or authentication codes are called, all that is left to do is define the database initialization strategy when the program launches and run a query on the database.

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);
}
52
7/24/2014 6:41:02 PM

Popular Answer

a non-destructive version based on the response from IMLiviu and his remarks:

I recently ran across this one issue and had to figure out how to do it correctly from the answer, the comments, and some trial and error, so I thought I'd provide the solutions so you may copy and paste them. Full credit should go to IMLiviu as they provided the basis for this. It alters the currentUserProfile and UserContext classes that seem to work with EF as-is directly:

After reading all the comments and developing a prototype, I was appalled to find a recommendation that called for totally destroying a database in order to add a few tables.

1 - Abandon Webmatrix development

Stop creating the membership tables using the usual webmatrix method (comment out the [InitializeSimpleMembership] attribute).

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

Make a migration configuration in step two.

Make a migration configuration class that looks something like this:

public class MigrationConfiguration : DbMigrationsConfiguration<UsersContext> 
{
    public MigrationConfiguration()
    {
        this.AutomaticMigrationsEnabled = true;  // This is important as it will fail in some environments (like Azure) by default
    }

    protected override void Seed(UsersContext context)
    {
        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
    }
}

3. Make EF creation pluralization-free.

AccountModel.cs should be modified.UsersContext class to exclude the possibility for pluralization (added the OnModelCreating event):

public class UsersContext : DbContext
{
    public UsersContext() : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }

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

4 - Expand UserProfile with new fields

You should add the additional fields to UserProfile.

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string UserEmail { get; set; }  // <<<<<<<< E.G. THIS ADDED
}

5 - Move the tables when the app launches.

Now, you configure the database init strategy and activate it with a read when the program launches:

    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(new MigrateDatabaseToLatestVersion<UsersContext, MigrationConfiguration>());
        new UsersContext().UserProfiles.Find(1);
    }

Naturally, you will need to add a number of using statements to make this all work, but the resolve option in the context menu on the right will take care of that for you.

Added information

If you choose (like I did) to use a different table than the oneUserProfile You must adjust various entries so that they correspond with your users.

  • As youSimpleMembershipInitializer you must reference the new table and column names in your class.
  • You must cite your new model fields in the account controller and the different Login and Register pages (if the names have changed)
  • In theUsersContext the Userprofile classname may remain as-is, however you must modify theTable property to match the name of your table.
  • In theUserProfile class, you must rename the fields to reflect the names of the fields in your new table.
  • You must eliminate the connection between these two in the database.webpages_UsersInRoles and UserProfile should provide a connection between your new user table andwebpages_UsersInRoles else you risk having run-time failure due to the previous referential integrity tests. (I firmly advise you to remove the currentUserProfile check to see if it hasn't been rebuilt. If so, your code has a remnant (if it is).


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow