在MVC4中播种数据和创建/管理角色 - 它有多难?

时间:2013-01-27 13:54:42

标签: asp.net-mvc-4 visual-studio-2012 simplemembership

我快要疯了,所以我会再试一次帮助...... 我正在使用Visual Studio Express 2012 for Web使用C#+ MVC4 + Razor + Entity Framework + ASP.NET 4.5创建一个Internet项目。 我需要执行以下操作:自动创建“admin”用户(将在整个站点上授权),然后创建一些用户角色。 我已经阅读了关于SimpleMembership,角色和整个网络上所有内容的内容,但似乎没有什么能让我有一个直截了当的方法让整个过程发挥作用。

这是我到目前为止所做的:

1 - 创建了一个DataContext类:

public class DataContext : DbContext
{
public DataContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}

2 - 创建了一个初始化类,我假设它会让我创建管理员用户和管理员角色:

public class DataContextDbInitializer : DropCreateDatabaseAlways<DataContext>
{
protected override void Seed(DataContext context)
{
var roles = (Webmatrix.WebData.SimpleRoleProvider)System.Web.Security.Roles.Provider;
var membership = (Webmatrix.WebData.SimpleMembershipProvider)System.Web.Security.Membership.Provider;
if (!roles.RoleExists("Admins")) {
roles.CreateRole("Admins");
}
if (membership.GetUser("admin", false) == null) {
membership.CreateUserAndAccount("admin", "123456");
}
if (!roles.GetRolesForUser("admin").Contains("Admins")) {
roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
} 
}
}

(我尝试从DropCreateDatabaseIfModelChanges继承,但这没有帮助。)

3 - 在Global.asax中为App_Start方法添加了两行:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
Database.SetInitializer<DataContext>(new DataContextDbInitializer());

我也尝试在DataContextDbInitializer类的Seed方法中使用WebSecurity.InitializeDatabaseConnection,但是没有用。

4 - 从AccountController中删除了[InitializeSimpleMembership]注释,因此我可以从应用程序生命周期的最开始初始化它(使用App_Start中的WebSecurity.InitializeDatabaseConnection,正如我在3)。我尝试在HomeController中的Index方法之上添加[InitializeSimpleMembership]并从App_Start中删除WebSecurity.InitializeDatabaseConnection,但这也无济于事。

5 - 在Web.config中,我将身份验证方法作为表单(默认),并保留默认连接字符串:

<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-TPFinal-20130121210447;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-TPFinal-20130121210447.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>

并将其添加到system.web标记内:

<roleManager enabled="true" cacheRolesInCookie="true" />

6 - 然后,为了测试一切是否正常,我在HomeController的About()方法的顶部使用[Authorize(Roles =“Admins”)]注释。如果事情按预期工作,这应该迫使我以admin / 123456登录,以便能够看到由HomeController / About控制的“关于”页面。

7 - 我没有添加EF迁移或其他任何内容。默认情况下,所有其他内容都是VS2012自动创建的。 所以我运行我的应用程序,然后单击“关于”链接,我会看到登录表单(这意味着[Authorize(Roles =“Admins”)]注释正在执行预期的操作)。我尝试以admin / 123456身份登录,但每次单击登录按钮时,会反复重新加载登录页面。

我注意到的一些事情:

- 如果我在Seed方法中添加一个断点,它似乎没有被调用。

- 当我使用DropCreateDatabaseAlways再次运行应用程序时,我能够以admin / 123456身份登录,这让我再次想到我的整个DataContextDbInitializer类甚至没有被使用,因为我认为应该创建数据库从头开始,这将删除管理员用户。

我不知道还有什么要读的,还有什么可以尝试的......我是asp.net的新手(需要我这么说吗?)并且疯了。 谢谢!

3 个答案:

答案 0 :(得分:1)

最后,我设法让整个事情发挥作用!

我的种子方法现在看起来像这样:

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

if (!Roles.RoleExists("Admins"))
{
    Roles.CreateRole("Admins");
}
if (!WebSecurity.UserExists("admin"))
{
    WebSecurity.CreateUserAndAccount("admin", "123456");
}
if (!Roles.GetRolesForUser("admin").Contains("Admins"))
{
    Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
}
base.Seed(context);

Global.asax中的My App_Start如下所示:

Database.SetInitializer(new DataContextDbInitializer());
DataContext c = new DataContext();
c.Database.Initialize(true);

我不确定这是否真的在做什么,但我在Web.config中的system.web标记内有这个:

<roleManager enabled="true" cacheRolesInCookie="true" />

我还从AccountController中删除了[InitializeSimpleMembership],在AccountModels中删除了UsersContext类。我把这一点移到我自己的上下文类中:

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

然后,为了测试一切是否正常,我在HomeController的About()方法的顶部使用[Authorize(Roles =“Admins”)]注释。如果事情按预期工作,这应该强制我以admin / 123456登录,以便能够看到由HomeController / About控制的“关于”页面。哪个;)

感谢您的帮助!这有助于我更多地了解正在发生的事情。

答案 1 :(得分:1)

在MVC4中,默认的Internet应用程序内置了身份验证。名为InitializeSimpleMembershipAttribute的类位于Filters目录中。顾名思义,这个类初始化简单成员资格数据库。如果你看一下构造函数,你会看到以下行:

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

在此行下方,您可以插入以下代码以创建默认用户:

// Create admin user.
                    if (!WebSecurity.UserExists("admin"))
                    {
                        WebSecurity.CreateUserAndAccount("admin", "12345678!");
                    }

另一种做事的方式。

答案 2 :(得分:0)

试试这样:

public class DataContextDbInitializer : DropCreateDatabaseAlways<DataContext>
{
    protected override void Seed(DataContext context)
    {
        if (!Roles.RoleExists("Admins"))
        {
            Roles.CreateRole("Admins");
        }
        if (!WebSecurity.UserExists("admin"))
        {
            WebSecurity.CreateUserAndAccount("admin", "123456");
        }
        if (!Roles.GetRolesForUser("admin").Contains("Admins"))
        {
            Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
        }
    }
}

和您的Application_Start

Database.SetInitializer<DataContext>(new DataContextDbInitializer());
using (var ctx = new DataContext())
{
    ctx.Database.Initialize(true);
}
WebSecurity.InitializeDatabaseConnection(
    "DefaultConnection", 
    "UserProfile", 
    "UserId", 
    "UserName", 
    autoCreateTables: true
);