【问题标题】:ASP.NET MVC 5 Custom RoleProvider cannot retrieve roles from database for usernameASP.NET MVC 5 Custom RoleProvider 无法从数据库中检索用户名的角色
【发布时间】:2018-09-18 15:40:10
【问题描述】:

我使用 Autofac 和 asp.net MVC 5,以及通用存储库模式

我创建自定义 RoleProvider

自定义角色提供者

namespace Web.Utility.Classes
{
    class GoldenBodyProvider : RoleProvider
    {
        private readonly IUnitOfWork _unitOfWork;

        private readonly IService _service;

        public GoldenBodyProvider()
        {
        }

        public GoldenBodyProvider(IUnitOfWork unitOfWork, IService service)
        {
            _unitOfWork = unitOfWork;
            _service = service;
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            throw new NotImplementedException();
        }

        public override string[] GetRolesForUser(string username)
        {
            var role = (from u in  _service.UserRepository.GetAll()
                        join r in _service.RoleRepository.GetAll() on u.RoleId equals r.Id
                        where u.MobileNumber == username
                        select r.RoleInSystem).ToArray();
            return role;
        }

    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; }
    }
}

在名为User.IsInRole("Coach")的视图之一中(GetRolesForUser 方法在 RoleProvider 中被调用)。之后,在 RoleProvider 中的GetRolesForUser 方法中给我一个错误:

对象引用未设置为对象的实例。

错误指向_service.UserRepository.GetAll(),这个方法是通过autofact注入RoleProvider

来源错误:

第 31 行:public override string[] GetRolesForUser(string 用户名)

第 32 行:{

第 33 行:var role = (from u in _service.UserRepository.GetAll()

第 34 行:将 r 加入 _service.RoleRepository.GetAll() on u.RoleId 等于 r.Id

第 35 行:其中 u.MobileNumber == 用户名

源文件:I:\GBWork\GoldenBody\Web\Utility\Classes\GoldenBodyProvider.cs 行:33

GenericRepository 模式中的

GetAll() 方法是:

   public virtual List<T> GetAll()
        {
            return _t.AsParallel().ToList();
        }

我认为注射不能正常工作。

autofac 配置:

 #region Autofac

            var builder = new ContainerBuilder();
            #region Registery
            #region MVC Register
            //This allows you to add properties to your filter attributes and any matching dependencies that are registered in the container will be injected into the properties.
            builder.RegisterFilterProvider();

            // You can register controllers all at once using assembly scanning...
            builder.RegisterControllers(typeof(Global).Assembly);

            builder.RegisterModule<AutofacWebTypesModule>();


            builder.RegisterAssemblyTypes(Assembly.Load("ServiceLayer"))
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces()
                .InstancePerRequest();
            builder.RegisterType(typeof(GoldenBodyDb)).As(typeof(IUnitOfWork)).InstancePerRequest();
            #endregion
            #region WebApi
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); //Register WebApi Controllers
            //زیرا کنتلر های وب ای پی آی در همین اسمبلی می باشد
            #endregion
            #endregion
            var container = builder.Build();

            // Set the dependency resolver for Web API.
            var webApiResolver = new AutofacWebApiDependencyResolver(container);
            GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;

            // Set the dependency resolver for MVC.
            var mvcResolver = new AutofacDependencyResolver(container);
            DependencyResolver.SetResolver(mvcResolver);

            #endregion

我在哪里做错了?我的问题在哪里?有什么解决办法?

【问题讨论】:

  • 您是否调试并检查 _service_service.UserRepository_service.RoleRepository 是否为空?你也可以分享一下autofac配置吗?
  • 尝试删除GoldenBodyProvider 中的公共无参数构造函数。如果您在 Autofac 中正确注册了存储库类,则应使用具有自动注入参数的构造函数,并且将实例化这些存储库。如果您在问题中提供您的 autofac 配置,将会有所帮助。
  • @ChetanRanpariya 添加 autofac 配置,获取所有方法返回值
  • @Diana 添加了 autofac 配置,我删除了 GoldenBodyProvider(IUnitOfWork unitOfWork, IService service) 但同样的错误
  • @arman 看起来你的GoldenBodyProvider 没有被依赖注入实例化,因此_service 为空,从而导致此错误。

标签: c# asp.net-mvc autofac


【解决方案1】:

看起来您正在使用身份并实现自定义角色提供程序。我假设您没有使用 OWIN(在您的 autofac 配置中没有任何内容)。我还假设您没有使用 SignInManager、UserManager 或 AuthenticationManager,您只需使用在 &lt;system.web&gt; 中配置的 RoleManager,并将 &lt;roleManager&gt; 部分映射到您的 GoldenBodyProvider 类,并使用 &lt;authentication mode="Windows" /&gt;

如果我在这里做出错误的假设,我的答案将毫无用处。如果您在问题中包含此信息,那将非常有帮助。否则无法提供正确答案。

继续所有这些假设,据我所知,您不能将构造函数参数注入到这样配置的 RoleProvider 中。它需要一个无参数的构造函数。我能想到几种可能的解决方案:

解决方案一:尝试使用autofac属性注入,而不是构造函数参数的注入。您需要像这样注册您的提供程序(注意:您可能需要添加生命周期范围配置):

builder.RegisterType<GoldenBodyProvider>().PropertiesAutowired();

并将您的只读字段转换为可写属性:更改:

private readonly IService _service;
private readonly IUnitOfWork _unitOfWork;

到这里:

public IService _service { get; set; }
public IUnitOfWork _unitOfWork { get; set; }

(更新:上面的原代码将属性定义为private,我改成public。属性注入需要属性有一个公共的setter,所以这个方案不好如果您需要将您的属性保密。Here 您可以找到解决此问题的方法。)

更多关于属性注入的信息here

解决方案 2: 您可以在没有依赖注入的情况下实现您的 RoleProvider 方法,只需在每次需要使用时直接实例化身份数据库上下文,如this answer(查看代码示例以获取类AppRoleProvider)。

public class AppRoleProvider : RoleProvider
{
    public override string[] GetAllRoles()
    {
        using (var userContext = new UserContext())
        {
            ...  //Do the query with userContext and return some value
        }
    }
    ...
}

解决方案 3: 使用服务定位器,如 this answer 中所述。在无参数构造函数的代码中,执行显式 Resolve 以实例化您需要的字段。这个解决方案不是很干净。应避免在运行时访问容器并执行Resolve

【讨论】:

  • 第一个解决方案不起作用,我认为第二个解决方案是最好的。 &lt;authentication mode="Forms"&gt;
  • 抱歉,我的错误,autofac 属性注入要求属性具有公共设置器,它们不能是私有的。我为答案添加了更新。 Here 你可以找到解决方法。
  • 还是不行,可能问题出在我的仓库
猜你喜欢
  • 1970-01-01
  • 2015-07-17
  • 2019-08-22
  • 1970-01-01
  • 2015-02-01
  • 2013-11-10
  • 1970-01-01
  • 2019-02-16
  • 1970-01-01
相关资源
最近更新 更多