Cannot seed Users & Roles
Asked Answered
R

3

2

I am trying to seed users and roles into my database. Currently using Code First Entity Framework with Automatic Migrations in C# MVC4. Whenever I call

Update-Database -Force

I get the following error:

Running Seed method. System.InvalidOperationException: You must call the "WebSecurity.InitializeDatabaseConnection" method before you call any other method of the "WebSecurity" class. This call should be placed in an _AppStart.cshtml file in the root of your site. at WebMatrix.WebData.SimpleRoleProvider.get_PreviousProvider() at WebMatrix.WebData.SimpleRoleProvider.RoleExists(String roleName) at System.Web.Security.Roles.RoleExists(String roleName) at GratifyGaming.Domain.Migrations.Configuration.Seed(GratifyGamingContext context) in C:\Users\Unreal\Documents\Visual Studio 2010\Projects\GratifyGaming\GratifyGaming.Domain\Migrations\Configuration.cs:line 36 at System.Data.Entity.Migrations.DbMigrationsConfiguration1.OnSeed(DbContext context) at System.Data.Entity.Migrations.DbMigrator.SeedDatabase() at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase() at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration) at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore() at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run() You must call the "WebSecurity.InitializeDatabaseConnection" method before you call any other method of the "WebSecurity" class. This call should be placed in an _AppStart.cshtml file in the root of your site.

The offending line of code is the Role.Exists

I have tried putting the WebSecurity.InitializeDatabaseConnection in Global.asax, Seed(), and created an _AppStart.cshtml with no success. I have trawled the internet looking for a possible solution and none of them have worked (including other stack overflow articles). Some notable blog posts are below.

See code below.

[Configuration.cs]

 protected override void Seed(GratifyGaming.Domain.Models.DAL.GratifyGamingContext context)
    {
        var criteria = new List<Criterion>
        {
            new Criterion { ID = 1, IsMandatory=true, Name = "Gameplay", Description="The playability of the games core mechanics" },
            new Criterion { ID = 2, IsMandatory=true, Name = "Art Style", Description="The artistic feel of the game as a whole. Elements such as story, style and originality come into play." },
            new Criterion { ID = 3, IsMandatory=true, Name = "Longevity", Description="How long did this game keep you entertained?" },
            new Criterion { ID = 4, IsMandatory=true, Name = "Graphics", Description="How good does the game look?" }
        };

        criteria.ForEach(s => context.Criterion.AddOrUpdate(s));
        context.SaveChanges();


        if (!Roles.RoleExists("Administrator"))
            Roles.CreateRole("Administrator");

        if (!WebSecurity.UserExists("user"))
            WebSecurity.CreateUserAndAccount(
                "user",
                "password");

        if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
            Roles.AddUsersToRoles(new[] { "user" }, new[] { "Administrator" });
    }

The Criterion seed code works without fail.

[_AppStart.cshtml]

@{
 if (!WebSecurity.Initialized)
{
    WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId",
                                             "UserName", autoCreateTables: true);
}
}

Normal login to my site works perfectly with this located here.

[web.config]

 <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
  <providers>
    <clear/>
    <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
  </providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
  <providers>
    <clear/>
    <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
  </providers>
</membership>

[AccountModel.cs]

    [Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public virtual ICollection<Game> AttachedGames { get; set; }

    public virtual ICollection<UserGratificationRecord> GratificationHistory { get; set; }

    [ForeignKey("UserLevel")]
    public int? AcheivementID { get; set; }
    public virtual Acheivement UserLevel { get; set; }

    public int? NumOfGratifictions { get; set; }

}

UPDATE

I think the WebSecurity.InitializeDatabaseConnection is not even being run - I can place more than one in my Seed method, and not get the 'can only be called once' error that you would normally get.

My seed method is in my domain project along with all the models, while everything else is in a WebUI project. Not sure if this has anything to do with it.

Rondon answered 26/11, 2012 at 12:59 Comment(0)
R
0

Delete your existing reference to WebMatrix.WebData Add reference WebMatrix.WebData version 2. Error will stop.

Rondon answered 2/12, 2012 at 3:16 Comment(2)
how to reference WebMatrix.WebData version 2 please?Beamon
you can add this to web.config <compilation debug="true" targetFramework="4.5"> <assemblies> <add assembly="WebMatrix.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add assembly="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </assemblies> </compilation>Raynaraynah
H
4

Just put that lazy init into the top of your Seed method

protected override void Seed(GratifyGaming.Domain.Models.DAL.GratifyGamingContext context)
{
    if (!WebSecurity.Initialized)
    {
        WebSecurity.InitializeDatabaseConnection("DefaultConnection",
                                                 "UserProfile",
                                                 "UserId",
                                                 "UserName",
                                                 autoCreateTables: true);
    }
Hepatic answered 30/11, 2012 at 21:55 Comment(3)
Interestingly enough it can't find WebSecurity.Initialized in the Seed method - Error 3 'WebMatrix.WebData.WebSecurity' does not contain a definition for 'Initialized'Rondon
I was referencing an older version of WebMatrix.WebData in my domain project. I reference v2, added your code and now it works.Rondon
+1 for the if (!WebSecurity.Initialized). My Seed() method is being called twice! Strangely it appears that the second call is being triggered from within the body of Seed method itself (i.e. starting from a line of code where I access one of the DbSets which has been freshly created during the migration). Without the WebSecurity.Initialized check the second Seed() call causes "The "WebSecurity.InitializeDatabaseConnection" method can be called only once."Centripetal
P
1

In your App_Start, try adding:

        var configuration = new Data.Migrations.Configuration();
        var migrator = new DbMigrator(configuration);
        migrator.Update();

You will have to make your configuration.cs file public

  public class Configuration : DbMigrationsConfigurati

This should make your seed method get called when you run your program

Patella answered 2/12, 2012 at 0:43 Comment(1)
Thanks for your input TMan. Adding the code you have suggested gives the following error: Error 6 The type or namespace name 'Migrations' does not exist in the namespace 'WebMatrix.Data' (are you missing an assembly reference?)Rondon
R
0

Delete your existing reference to WebMatrix.WebData Add reference WebMatrix.WebData version 2. Error will stop.

Rondon answered 2/12, 2012 at 3:16 Comment(2)
how to reference WebMatrix.WebData version 2 please?Beamon
you can add this to web.config <compilation debug="true" targetFramework="4.5"> <assemblies> <add assembly="WebMatrix.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add assembly="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </assemblies> </compilation>Raynaraynah

© 2022 - 2024 — McMap. All rights reserved.