Can't connect to Database to execute Identity

2019-07-16 08:02发布

问题:

I've created a new application with ASP.NET MVC5, using Individual User Accounts for security and Code-First Migrations for the Models/Database modeling. All options are default.

I want to setup custom Users and Roles to it, so i created a Seed using RoleManager and UserManager just to populate the Database. It works fine, create 3 Users, 3 Roles and set each User's Role correctly.

I can log in to the application correctly. The problem is that i can't execute any Identity method using the User, which is the logged User, the only things that i can get is the User.Identity.IsAuthenticated value, and the User.Identity.Name, which are correct. Every other method like Roles.GetRolesForUser("John"), or User.IsInRole("Student"), always generates this exception:

ProviderException : The Role Manager feature has not been enabled.

So okay, as in this article, i managed to insert the the <roleManager enabled="true" /> in the Web.config, and now it takes a really long time to respond, and generates Exceptions like:

Referring to:

Roles.IsUserInRole("Student")

Generates:

HttpException

Referring to:

Roles.GetRolesForUser(User.Identity.Name)

Generates:

NullReferenceException

Accessing the About page with a User in Student role logged in:

[Authorize(Roles="Teacher")]
public ActionResult About()
{
    ViewBag.Message = "Your application description page.";

    return View();
}

Generates:

SqlException
HttpException

It's like i have no connection to the Database at all, which is LocalDB, automatically generated and i could populate in the Seed Method and even make Login to the application.

I could even load data from the AspNetUsers table and show it in the View using the code below:

using (Models.ApplicationDbContext db = new Models.ApplicationDbContext())
{
    List<Models.ApplicationUser> Users = db.Users.ToList();

    ViewBag.Users = Users;
}

return View();

PLEASE HELP :'(


Here's the Seed code, that works fine, so it can connect to the Database using the Identity engine.

protected override void Seed(LocalBDAuthTest.Models.ApplicationDbContext context)
{
    #region Create Roles Student, Teacher e Administrator

    var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

    // Student
    if (!RoleManager.RoleExists("Student"))
    {
        RoleManager.Create(new IdentityRole("Student"));
    }

    // Teacher
    if (!RoleManager.RoleExists("Teacher"))
    {
        RoleManager.Create(new IdentityRole("Teacher"));
    }

    // Administrator
    if (!RoleManager.RoleExists("Administrator"))
    {
        RoleManager.Create(new IdentityRole("Administrator"));
    }

    #endregion

    #region Create Users for Student, Teacher e Administrator Roles.

    var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));


    // Create a Student user and set it's role to Student
    if (!context.Users.Any(u => u.UserName == "John"))
    {
        var Student = new ApplicationUser() { UserName = "John" };
        var Result = UserManager.Create(Student, "123456");
    }
    if (!UserManager.FindByName("John").Roles.Any())
    {
        UserManager.AddToRole(UserManager.FindByName("John").Id, "Student");
    }


    // Create a Teacher user and set it's role to Teacher
    if (!context.Users.Any(u => u.UserName == "Arnold"))
    {
        var Teacher = new ApplicationUser() { UserName = "Arnold" };
        var Result = UserManager.Create(Teacher, "123456");
        UserManager.AddToRole(Teacher.Id, "Teacher");
    }
    if (!UserManager.FindByName("Arnold").Roles.Any())
    {
        UserManager.AddToRole(UserManager.FindByName("Arnold").Id, "Teacher");
    }


    // Create a Administrator user and set it's role to Administrator
    if (!context.Users.Any(u => u.UserName == "Caroline"))
    {
        var Administrator = new ApplicationUser() { UserName = "Caroline" };
        var Result = UserManager.Create(Administrator, "123456");
        UserManager.AddToRole(Administrator.Id, "Administrator");
    }
    if (!UserManager.FindByName("Caroline").Roles.Any())
    {
        UserManager.AddToRole(UserManager.FindByName("Caroline").Id, "Administrator");
    }

    #endregion
    }

回答1:

This is due to having a mix of both ASP.NET Identity and ASP.NET Membership, having done this:

<system.web>
    <roleManager enabled="true" />
</system.web>

You enabled membership SqlRoleProvider, which use the role store in the default SQL Express instance in a database in your Web site's \app_dir folder.

If you open your machine.config, you'll find:

<connectionStrings>
  <add name="LocalSqlServer" 
    connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;
      AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
      providerName="System.Data.SqlClient"/>
</connectionStrings>
.
.
.
<roleManager>
  <providers>
    <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" ...
</providers>
</roleManager>

Most likely you don't have SQL Express installed, and that's why you are getting timeouts and SQL exceptions.

For ASP.NET Identity DON'T use System.Web.Security.Roles (it is part of the ASP.NET Membership) but use Microsoft.AspNet.Identity.RoleManager instead.