簡體   English   中英

無法訪問已處置的 object Asp.net Identity Core

[英]Cannot access a disposed object Asp.net Identity Core

我收到這個錯誤

System.ObjectDisposedException
  HResult=0x80131622
  Message=Cannot access a 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.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.AsyncDisposer.Dispose()
   at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.<MoveNext>d__5.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<ExecuteSingletonAsyncQuery>d__21`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.AspNetCore.Identity.UserManager`1.<FindByNameAsync>d__78.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.AspNetCore.Identity.UserValidator`1.<ValidateUserName>d__6.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Identity.UserValidator`1.<ValidateAsync>d__5.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.AspNetCore.Identity.UserManager`1.<ValidateUserAsync>d__172.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.AspNetCore.Identity.UserManager`1.<CreateAsync>d__74.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.AspNetCore.Identity.UserManager`1.<CreateAsync>d__79.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at EmployeeController.<Create>d__3.MoveNext() in Controllers\EmployeeController.cs:line 31

對於以下代碼

public class EmployeeController : Controller
{
    private readonly UserManager<Employee> userManager;
    public EmployeeController(UserManager<Employee> userManager)
    {
        this.userManager = userManager;
    }

    public ActionResult<string> Get()
    {
        return "Test Employee";
    }

    [HttpPost("Create")]
    public async void Create([FromBody]string employee)
    {
        var user = new Employee { UserName = "test@gmail.com", Email = "test@gmail.com" };
        var d = await userManager.CreateAsync(user, "1234567");
    }
}

啟動.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.AddDbContext<ApplicationDbContext>(options =>
         options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<Employee, IdentityRole>(opts =>
       {
           opts.Password.RequireDigit = false;
           opts.Password.RequireLowercase = false;
           opts.Password.RequireUppercase = false;
           opts.Password.RequireNonAlphanumeric = false;
           opts.Password.RequiredLength = 7;
           opts.User.RequireUniqueEmail = true;

       }).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

        services.AddAuthentication(opts =>
        {
            opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(cfg =>
        {
            cfg.RequireHttpsMetadata = false;
            cfg.SaveToken = true;
            cfg.TokenValidationParameters = new TokenValidationParameters()
            {
                // standard configuration
                ValidIssuer = Configuration["Auth:Jwt:Issuer"],
                ValidAudience = Configuration["Auth:Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),
                ClockSkew = TimeSpan.Zero,

                // security switches
                RequireExpirationTime = true,
                ValidateIssuer = true,
                ValidateIssuerSigningKey = true,
                ValidateAudience = true
            };
        });


            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();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseMvc();
    }
}

我需要在我的 DI 中注冊一些東西嗎? 我的印象是AddEntityFrameworkStores<ApplicationDbContext>()就足夠了。

你是一個async void受害者:

[HttpPost("Create")]
public async void Create([FromBody]string employee)
{
    var user = new Employee { UserName = "test@gmail.com", Email = "test@gmail.com" };
    var d = await userManager.CreateAsync(user, "1234567");
}

您正在調度等待的異步操作,並且上下文將在CreateAsyncawait context.SaveChangesAsync()之前CreateAsync

快速,明顯的解決方案

[HttpPost("Create")]
public async Task Create([FromBody]string employee)
{
    var user = new Employee { UserName = "test@gmail.com", Email = "test@gmail.com" };
    var d = await userManager.CreateAsync(user, "1234567");
}

但是,您應始終從Action返回IActionResult 這樣可以更輕松地更改響應代碼並顯示您的意圖:

[HttpPost("Create")]
public async Task<IActionResult> Create([FromBody]string employee)
{
    var user = new Employee { UserName = "test@gmail.com", Email = "test@gmail.com" };
    var d = await userManager.CreateAsync(user, "1234567");

    if (d == IdentityResult.Success)
    {
        return Ok();
    }
    else 
    {
        return BadRequest(d);
    }
}

我有同樣的問題,我忘記在我的 StartUp.cs 中添加 2 行:

services.AddScoped<UserManager, UserManager>();
services.AddScoped<RoleManager, RoleManager>();

添加它,它會正常工作!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM