【问题标题】:Cannot access a disposed object.\r\nObject name: 'UserManager`1 - while calling CreateAsync(user, model.password)无法访问已释放的对象。\r\n对象名称: 'UserManager`1 - 在调用 CreateAsync(user, model.password) 时
【发布时间】:2020-11-25 16:34:54
【问题描述】:

我正在开发 .net 核心项目。 我的项目结构有 4 个项目。

  1. Student_Database -(包含数据库表模型和ApplicinDBContext)
  2. Student_Entities -(包含所有 View 侧面模型)
  3. Student_Service - (所有从这里处理的数据库操作。它连接到数据库。 例如:IUserService 和 UserService)
  4. Student_Web -(控制器和所有方法、逻辑以及所有视图都在这个项目中)

我已经实现了实体框架核心。并尝试使用 Usermanager 插入数据。 现在,当我从控制器(Student_Web)调用方法“CreateAsync”时,它可以正常工作并插入用户。 但是我想在Student_Service中实现数据库操作。因此,当我从 UserService 调用“CreateAsync”时,会出现错误“无法访问已处置的对象。\r\n对象名称:'UserManager`1”

我正在从控制器调用这个接口 IUserService。所以这是我在 UserService 中的代码。

请帮我解决这个问题。

public class UserService : IUserService
{
    #region Properties

    private readonly IDbContext _context;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<IdentityRole<int>> _roleManager;

    #endregion

    #region Consturctor

    public UserService(
        IDbContext context
        , UserManager<ApplicationUser> userManager
        , RoleManager<IdentityRole<int>> roleManager
    {
        _context = context;
        _userManager = userManager;
        _roleManager = roleManager;
    }
    #endregion

    #region Methods
        
    public async Task<bool> Create(NewUsers model)
    {
        bool result = false;
        try
        {
            var user = await _userManager.FindByNameAsync(model.UserName);
            if (user == null)
            {
                model.Password = GeneratePassword();
                user = new ApplicationUser
                {
                    //Id = 10,
                    UserName = model.UserName,
                    Email = model.UserName,
                    AccessFailedCount = 0,
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    CreatedBy = 2,
                    CreatedDate = DateTime.UtcNow,
                    Active = false
                };
                    
                var returnResult = await _userManager.CreateAsync(user, model.Password);
                if (returnResult.Succeeded)
                {
                    returnResult = await _userManager.AddToRoleAsync(user, _roleManager.Roles.Where(x=>x.Id == model.RoleId).Select(x => x.Name).FirstOrDefault());
                }
                if (model.CompanyId!= null)
                {
                    foreach (var item in model.CompanyId)
                    {
                        var userMap = new UserCompanyMapping();
                        userMap.UserId = user.Id;
                        userMap.CompanyId = item;
                        _userCompanyMappingRepository.Insert(userMap);
                    }
                }
                result = returnResult.Succeeded;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
        return result;
    }
    #endregion
}

//startup class

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(option =>
        {
            var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
            option.Filters.Add(new AuthorizeFilter(policy));
        });
        
        services.AddDbContextPool<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentityCore<ApplicationUser>();
        // Register Dependencies extra service
        services.AddAppServices();
            
        services.AddIdentity<ApplicationUser, IdentityRole<int>>(options =>
        {
            options.User.RequireUniqueEmail = true;
            options.Password.RequireNonAlphanumeric = false;
        })
       .AddRoles<IdentityRole<int>>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();

        services.ConfigureApplicationCookie(option =>
        {
            option.LoginPath = "/login";
            option.AccessDeniedPath = "/Login/AccessDenied";
        });

        // Register dependancy
        RegisterAutoMapper(services);
        RegisterServices(services);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
        app.ConfigureRequestPipeline();
        app.UseStaticFiles();
        app.UseAuthentication();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            //register all routes
            EngineContext.Current.Resolve<IRoutePublisher>().RegisterRoutes(endpoints);
        });
        //app.UseEndpoints(endpoints =>
        //{
        //    endpoints.MapControllerRoute(
        //        name: "default",
        //        pattern: "{controller=Login}/{action=Index}/{id?}");
        //});
    }

    private void RegisterServices(IServiceCollection services)
    {
        // Get class libraryGetAssembly(ty)
        var serviceLibraries = Assembly.Load("Student.Services")
            .GetTypes()
            .Where(x => x.IsClass && x.GetInterfaces().Any() && x.Namespace.Contains(".Services.Services"))
            .ToList();

        if (serviceLibraries != null && serviceLibraries.Count > 0)
        {
            foreach (var service in serviceLibraries)
            {
                var interfaceType = service.GetInterfaces().FirstOrDefault();
                services.AddScoped(interfaceType, service);
            }
        }
    }

    private void RegisterAutoMapper(IServiceCollection services)
    {
        // Auto Mapper Configurations
        var mappingConfig = new MapperConfiguration(mc =>
        {
            mc.AddProfile(new MappingProfile());
        });

        IMapper mapper = mappingConfig.CreateMapper();
        services.AddSingleton(mapper);
    }
}

//Action controller method



namespace Student.Web.Controllers
{
    [Authorize]
    public class UserController : Controller
    {
        private readonly IUserService userService;
        private readonly ICommonService commonService;

        public UserController(
            IUserService userService,
            ICommonService commonService)
        {
            this.userService = userService;
            this.commonService = commonService;
        }

        public IActionResult Index()
        {
            return View();
        }
        
        [HttpGet]
        public IActionResult Create()
        {
            ViewBag.RoleList = commonService.GetRoles().Result;
            ViewBag.CompanyList = commonService.GetCompanies().Result;
            ViewBag.CityList = commonService.GetCities().Result;
            ViewBag.CompanyAccessList = commonService.GetCompanyAccessListMultiCheck().Result;
            return View();
        }

        [HttpPost]
        public IActionResult Create(UserAddModel model)
        {
            if (ModelState.IsValid)
            {
                var response = userService.Create(model);
            }
            return RedirectToAction("Index");
        }
    }
}

【问题讨论】:

  • 您能告诉我们您是如何在startup classAction that calls the service 中注册服务的吗?
  • @Hameed,我已经编辑了我的帖子,其中我添加了启动类和控制器的代码,我从中调用了 UserService。谢谢。并使用 automapper 我将 UserAddModel 转换为 NewUser 类

标签: c# asp.net-core asp.net-identity claims-based-identity ef-core-3.1


【解决方案1】:

对您的service 的调用永远不会是awaited,所以它有点变成了fire-and-forget,这意味着请求可能会在服务完成其工作之前结束,这会导致所请求的服务被处理掉。

要解决此问题,您需要通过执行以下操作稍微更改您的 Create Action

  1. 让您的操作async 并让它返回Task&lt;IActionResult&gt;
  2. 等待服务。
        [HttpPost]
        public async Task<IActionResult> Create(UserAddModel model)
        {
            if (ModelState.IsValid)
            {
                var response = await userService.Create(model);
            }
            return RedirectToAction("Index");
        }

那么它应该可以正常工作。

【讨论】:

  • 非常感谢。我真的很感谢你的帮助。我花了一整天才找到解决方案,但我没有得到任何解决方案。最后你给了我完美的解决方案。再次感谢。 @Hameed
  • 我很高兴能帮上忙 :D
猜你喜欢
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2022-01-11
  • 2020-04-23
相关资源
最近更新 更多