ASP.NET MVC 5自定义RoleProvider无法获取用户角色问题求助
Hey there, let's break down why your GoldenBodyProvider isn't pulling roles from the database correctly. The core issue here is how ASP.NET instantiates RoleProvider classes—it uses the parameterless constructor by default, which means your constructor with IUnitOfWork and IService never gets called. Those dependencies end up null when you try to use them in IsUserInRole.
Here's how to fix this step by step:
1. Adjust Your RoleProvider for Dependency Injection
First, modify your GoldenBodyProvider to use property injection and hook into the Initialize method to pull dependencies from Autofac after ASP.NET creates the instance:
namespace Web.Utility.Classes { public class GoldenBodyProvider : RoleProvider { // Public properties for Autofac to inject public IUnitOfWork UnitOfWork { get; set; } public IService Service { get; set; } public override void Initialize(string name, NameValueCollection config) { base.Initialize(name, config); // Resolve dependencies from Autofac's container var container = DependencyResolver.Current.GetService<IContainer>(); UnitOfWork = container.Resolve<IUnitOfWork>(); Service = container.Resolve<IService>(); } public override bool IsUserInRole(string username, string roleName) { // Now you can safely use your dependencies here // Example implementation (adjust to your repository logic): var user = UnitOfWork.Users.FirstOrDefault(u => u.Username == username); if (user == null) return false; return user.Roles.Any(r => r.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase)); } // Don't forget to implement all required abstract methods from RoleProvider public override string[] GetRolesForUser(string username) { var user = UnitOfWork.Users.FirstOrDefault(u => u.Username == username); return user?.Roles.Select(r => r.Name).ToArray() ?? Array.Empty<string>(); } // Implement remaining abstract methods (fill in or throw NotImplementedException as needed) public override void CreateRole(string roleName) => throw new NotImplementedException(); public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) => throw new NotImplementedException(); public override bool RoleExists(string roleName) => throw new NotImplementedException(); public override void AddUsersToRoles(string[] usernames, string[] roleNames) => throw new NotImplementedException(); public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) => throw new NotImplementedException(); public override string[] GetUsersInRole(string roleName) => throw new NotImplementedException(); public override string[] GetAllRoles() => throw new NotImplementedException(); public override string[] FindUsersInRole(string roleName, string usernameToMatch) => throw new NotImplementedException(); public override string ApplicationName { get; set; } } }
2. Ensure Autofac is Configured Correctly
Make sure your Autofac container registers your dependencies properly in Global.asax.cs or your dedicated Autofac config class:
var builder = new ContainerBuilder(); // Register MVC controllers builder.RegisterControllers(typeof(MvcApplication).Assembly); // Register your unit of work and service (adjust lifetimes to match your app's needs) builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest(); builder.RegisterType<Service>().As<IService>().InstancePerRequest(); // Set Autofac as the dependency resolver var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
3. Verify Web.Config Setup
Double-check that your custom role provider is enabled in web.config under <system.web>:
<system.web> <roleManager enabled="true" defaultProvider="GoldenBodyProvider"> <providers> <clear /> <add name="GoldenBodyProvider" type="Web.Utility.Classes.GoldenBodyProvider" /> </providers> </roleManager> </system.web>
Key Notes:
- Why Property Injection? ASP.NET creates
RoleProviderinstances via the default constructor, so constructor injection won’t work. TheInitializemethod is the standard hook to resolve dependencies post-instantiation. - Implement All Abstract Methods:
RoleProvideris an abstract class, so you need to implement every method—even if some throwNotImplementedExceptiontemporarily (fill in the ones your app actually uses). - Lifetimes: Using
InstancePerRequestforIUnitOfWorkis standard in MVC to ensure each request gets its own isolated unit of work instance.
Once you make these changes, your IsUserInRole method will have access to your database via the injected dependencies, allowing you to fetch and check user roles correctly.
内容的提问来源于stack exchange,提问作者arman

