【问题标题】:Can't get Users with roles Asp.net MVC5 identity 2.2.1 dependency injection无法获得具有角色的用户 Asp.net MVC5 身份 2.2.1 依赖注入
【发布时间】:2016-10-20 00:50:10
【问题描述】:

大家好!

在阅读了my previous questionMRebati 提示后,我搜索并了解了blog 的重要性,不将统一和OWIN 混合以及如何依赖注入ASP.net 身份。

所以首先我不想被标记为问同样的问题,即使我是,但现在我的代码与上一个问题相比发生了一些变化。

无论如何,现在我收到了不同的错误消息:

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

这意味着我在调用我的自定义用户管理器时仍然为空。

我想要的结果是获得我的所有用户及其接受角色的列表:

XXXXXX ------ 管理员

YYYYYY ------ 经理

关于我的项目的信息:

MVC:5.2.3

身份:2.2.1

实体框架:代码优先 2.2.1

我还尝试在 Unity 中使用依赖注入。

这是我的代码:

控制器:

public ActionResult GetUsersWithRoles(string roleName)
        {

            ViewBag.UsersWithRoles = _userManager.GetUsersInRole(context, roleName);


            return View(ViewBag.UsersWithRoles);
        }

我在 IdentityConfig.cs 中的自定义用户管理器:

    public class ApplicationUserManager : UserManager<ApplicationUser>
        {
            public ApplicationUserManager(IUserStore<ApplicationUser> store)
                : base(store)
            {
/// the create part which is moved from the default /// 
          public IQueryable<ApplicationUser> GetUsersInRole(ApplicationDbContext context, string roleName)
                {
                    if (context !=null && roleName !=null)
                    {
                        var roles = context.Roles.Where(r => r.Name == roleName);
                        if (roles.Any())
                        {
                            var roleId = roles.First().Id;
                            return from user in context.Users
                                   where user.Roles.Any(r => r.RoleId == roleId)
                                   select user;
                        }
                    }

                return null;
            }

最后是我的观点:

@using (Html.BeginForm("GetUsersWithRoles", "Roles"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <h3>Roles for this user </h3>

    foreach (IQueryables in ViewBag.UsersWithRoles)
    {
        <tr>

            <td>@s</td>
        </tr>
    }


}

这是我的 unityConfig.cs

using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using eCommerce.DAL.Repositories;
using eCommerce.Model;
using eCommerce.Contracts.Repositories;
using eCommerce.WebUI.Controllers;
using eCommerce.WebUI.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace eCommerce.WebUI.App_Start
{

    public class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });


        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion


        public static void RegisterTypes(IUnityContainer container)
        {

            container.RegisterType<IRepositoryBase<Customer>, CustomerRepository>();
            container.RegisterType<IRepositoryBase<Product>, ProductRepository>();
            container.RegisterType<IRepositoryBase<Basket>, BasketRepository>();
            container.RegisterType<IRepositoryBase<Voucher>, VoucherRepository>();
            container.RegisterType<IRepositoryBase<VoucherType>, VoucherTypeRepository>();
            container.RegisterType<IRepositoryBase<BasketVoucher>, BasketVoucherRepository>();
            container.RegisterType<IRepositoryBase<BasketItem>, BasketItemsRepository>();
            //container.RegisterType<AccountController>(new InjectionConstructor());
            container.RegisterType<ApplicationDbContext>(new PerRequestLifetimeManager());
            container.RegisterType<ApplicationUserManager>();
            container.RegisterType <IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(typeof(ApplicationDbContext)));


        }
    }
}

这是 RolesController.cs 的构造函数:

 private ApplicationDbContext context;
        private ApplicationUserManager _userManager;

        public RolesController(ApplicationDbContext context, ApplicationUserManager _userManager)
        {

            this.context = context;
            this._userManager = _userManager;
        }

这是我的 startup.cs: 一个

ssembly: OwinStartupAttribute(typeof(eCommerce.WebUI.Startup))]
namespace eCommerce.WebUI
{
    public partial class Startup
    {
        internal static IDataProtectionProvider DataProtectionProvider { get; private set; }

        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            //app.CreatePerOwinContext(ApplicationDbContext.Create);
            //app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>()); // <-
            DataProtectionProvider = app.GetDataProtectionProvider();

        }



    }
}

这是我的 Global.asax:

 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            AreaRegistration.RegisterAllAreas();

            var context = new ApplicationDbContext();
            if (!context.Users.Any(user => user.UserName == "Email@hotmail.com"))
            {
                var userStore = new UserStore<ApplicationUser>(context);
                var userManager = new UserManager<ApplicationUser>(userStore);
                var applicationUser = new ApplicationUser() { UserName = "Email@hotmail.com" };
                userManager.Create(applicationUser, "Password");

                var roleStore = new RoleStore<IdentityRole>(context);
                var roleManager = new RoleManager<IdentityRole>(roleStore);
                roleManager.Create(new IdentityRole("Admin"));

                userManager.AddToRole(applicationUser.Id, "Admin");

            }
        }

    }

从我的角色控制器创建方法:

[HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                context.Roles.Add(new IdentityRole
                {
                    Name = collection["RoleName"]
                });
                context.SaveChanges();
                ViewBag.ResultMessage = "Role created successfully !";
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

感谢您的宝贵时间。

【问题讨论】:

  • 你从哪里得到 NullReferenceException?您需要修改您的问题,以显示您如何使用 Unity 设置依赖项。
  • 我已经包含了 unityconfig
  • 我在这里仍然看不够。我不知道你的GetUsersInRole 方法属于哪个类,或者它实现了哪些接口。我不知道你的控制器的构造函数是什么样的(假设构造函数注入。)。我看不到您如何使用 ASP.NET 注册 Unity 容器。考虑一下需要向某人展示以诊断您的问题的整个事情链。阅读MCVE
  • 完成了,也许吧?谢谢你的链接!有趣的阅​​读。
  • 所以如果你做到了那么远,依赖注入可能设置正确。究竟什么是空?用 NullReferenceException 弄清楚这始终是最重要的事情。我注意到您认为您在 foreach 声明中使用了 string,即使 ViewBag.UsersWithRolesIQueryable&lt;ApplicationUser&gt;。所以你有一个不匹配的地方。永远不要使用 ViewBag - 通过强类型模型将信息从控制器传递到视图。此外,将IQueryable 传递给视图也不是一个好主意,这会导致您的视图进行数据访问。

标签: c# asp.net asp.net-mvc dependency-injection asp.net-identity


【解决方案1】:

最好在UserManager 中保留对 DbContext 的引用:

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    private readonly ApplicationDbContext context;

    public ApplicationUserManager(ApplicationDbContext context, /*... other parameters*/) : base(store)
    {
        this.context = context;
        //... other configuration bits
    }

    public IEnumerable<ApplicationUser> GetUsersInRole(string roleName)
    {
        if (String.IsNullOrWhiteSpace(roleName))
        {
            throw new ArgumentNullException(nameof(roleName));
        }

        var role = context.Roles.FirstOrDefault(r => r.Name == roleName);

        if (role == null)
        {
            throw new Exception($"Role with this name not found: {roleName}");
        }

        var users = context.Users.Where(u => u.Roles.Any(r => r.RoleId == role.Id)).ToList();

        return users;
    }

    // the rest of User manager methods
}

在您的控制器中避免使用ViewBag - 这不是一个好习惯。此外,正如已经提到的,永远不要将IQueryable 传递给您的视图。粗略地说IQueryable 是一个SQL 查询,但IEnumerable 是一个对象的集合。 View 只需要知道对象。所以你的控制器看起来像这样:

public class UsersWithRoleController : Controller
{
    private readonly ApplicationUserManager userManager;

    public UsersWithRoleController(ApplicationUserManager userManager)
    {
        this.userManager = userManager;
    }

    public ActionResult GetUsersWithRoles(string roleName)
    {
        var users = userManager.GetUsersInRole(roleName);

        var viewModel = new GetUsersWithRolesViewModel()
        {
            RoleName = roleName,
            Users = users,
        };

        return View(viewModel);
    }

}

public class GetUsersWithRolesViewModel
{
    public String RoleName { get; set; }
    public IEnumerable<ApplicationUser> Users { get; set; }
}

视图将是:

@model IoCIdentity.Controllers.GetUsersWithRolesViewModel

@{
    ViewBag.Title = "title";
}

<h2>List of users in role @Model.RoleName</h2>

<ul>
    @foreach (var user in @Model.Users)
    {
        <li>@user.UserName</li>
    }
</ul>

您可以在我的github 中获取完整示例。虽然我没有正确测试它——我的数据库现在坏了——(

【讨论】:

  • 对不起,还是同样的问题,可能是因为我在 Global.asax 文件中写的内容吗?我的意思是您的代码非常有意义,并且易于遵循。很奇怪,我调试的时候连Getuserswithroles这个方法都没有输入。我去看看你的github。
  • @Habbex 你需要找出究竟什么是空的以及它在哪里。否则我们无法提供帮助。我将从删除Global.asax.cs 中的用户/角色初始化开始,然后将解决方案精简到最低限度。
  • 是的,这就是现在的计划,如果有什么事情我会联系你。再次感谢您的帮助!
  • 该死.. 在阅读了您关于 Asp.Net MVC ViewBag is BAD!!! 的帖子后,我的项目在特定于用户角色管理方面更像是一个 Viewbag-View-Controller 而不是 Model-View-Controller。奇怪的是,我可以通过视图传递并让我的所有用户进入一个 dropboxlist,就像我从教程网站获取角色一样,这让我一开始就陷入了这个混乱......该死的我只是不知道这件事viewbags 等.. 所以我会寻找更正确的方法来分配用户角色,然后重试.. 谢谢!
  • 我已将您建议的代码移动到单独的视图中,以便更好地理解,并摆脱混淆调试过程的视图包。完成后,代码最终调用了 GetUsersInRoles 方法,但接缝找不到 RoleName。并停在:throw new ArgumentNullException(nameof(roleName)); 并显示以下错误消息:值不能为空。参数名称:角色名称。我怀疑它与我从教程站点获得的创建新角色方法有关。我会尽快更新并发布我的 github。
猜你喜欢
  • 2011-03-18
  • 2015-10-20
  • 2020-03-10
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
相关资源
最近更新 更多