ASP.NET Core injecting DbContext

0

I get this error in the "catch" when injecting data: Can not access to disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose () on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'AsyncDisposer'.

HomeController.cs

public class HomeController : Controller
{


    public HomeController(IServiceProvider serviceProvider)
    {
        CreateRoles(serviceProvider);

    }
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    }

    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";

        return View();
    }

    public IActionResult Privacy()
    {
        return View();
    }


    private async Task CreateRoles(IServiceProvider serviceProvider)
    {

        string msg=string.Empty;

        try
        {

            var rolesManger = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

            var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();


            String[] rolesName = { "Admin", "User", "SuperAdmin" };

            foreach (var item in rolesName)
            {
                var existeRoles = await rolesManger.RoleExistsAsync(item);

                if (!existeRoles) 
                {
                    await rolesManger.CreateAsync(new IdentityRole(item));
                }

            }


           var usr = await userManager.FindByIdAsync("705f393e-d494-4bef-8b59-e542a44c53f3");
            await userManager.AddToRoleAsync(usr, "Admin");


        }
        catch (Exception ex)
        {
            msg = ex.Message;

        }


    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}

}

Startup.cs:

 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.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        //services.AddDefaultIdentity<IdentityUser>()
          //  .AddEntityFrameworkStores<ApplicationDbContext>();
        services.AddIdentity<IdentityUser,IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

I have searched in google but no solution is useful, please give me a hand to solve it, thank you very much

    
asked by Fares Saadouni 22.10.2018 в 22:01
source

1 answer

0

The problem is that the CreateRoles method is asynchronous and you are invoking it in the constructor which can not be asynchronous.

The flow of the execution will not "wait" until the method is finished and will start to execute the action of the controller, once the action ends the framework discards the resources whose life cycle corresponds to only the duration of the request such as UserManager . It is possible that at this point, the CreateRoles method continues with its execution, having reference to objects that have been discarded ( disposed ).

Seeing the code, I assume you want to ensure that there are roles before the rest of the program runs. What I recommend is that you get that initialization from the driver's constructor, the constructor is not a good place to put it. You could put it in a Middleware before executing the regular MVC flow.

This is how you create a middleware:

public class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IServiceProvider _serviceProvider;

    public MyMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
    {
        _next = next;
        _serviceProvider = serviceProvider;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        // tu código

        await _next(httpContext);
    }
}

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyMiddleware>();
    }
}

and you register it in Startup :

app.UseAuthentication();
app.UseMyMiddleware();
app.UseMvc(routes => //...

the order is important here, make sure it is registered after authentication and before MVC.

    
answered by 22.10.2018 в 22:39