简体   繁体   中英

Cannot access a disposed object.\r\nObject name: 'UserManager`1 - while calling CreateAsync(user, model.password)

I am working on .net core porject. My Project structure has 4 projects.

  1. Student_Database - (Contains Database table model and ApplicatinDBContext)
  2. Student_Entities - (Contains All the View side models)
  3. Student_Service - (All the Database operation handling from here. It is connected to Database. ex: IUserService and UserService)
  4. Student_Web - ( Controllers and all the methods, logic along with all the views are in this project)

I have implemented Entity Framework core. And try to using Usermanager for insert data. Now when I am calling method "CreateAsync" from controller(Student_Web) it works fine and user inserted. But I want to implement database operation in Student_Service. So when I am calling "CreateAsync" from UserService it gives me error "Cannot access a disposed object.\r\nObject name: 'UserManager`1"

I am calling this interface IUserService from controller. So here is my code in UserService.

Please help me to solve this.

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

The call to your service is never awaited , so it is kind of became fire-and-forget which means the request might ends before the service finishes its job which would cause the requested services to get disposed.

To fix that you need to alter your Create Action a little bit by doing the followings:

  1. Make your action async and let it return Task<IActionResult> .
  2. Await the service.
        [HttpPost]
        public async Task<IActionResult> Create(UserAddModel model)
        {
            if (ModelState.IsValid)
            {
                var response = await userService.Create(model);
            }
            return RedirectToAction("Index");
        }

Then it should work just fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM