[英]Cannot access a disposed object Asp.net Identity Core
I am getting this error我收到这个错误
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
For the following code对于以下代码
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");
}
}
Startup.cs启动.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();
}
}
Do I need to register something into my DI?我需要在我的 DI 中注册一些东西吗? I was under the impression that
AddEntityFrameworkStores<ApplicationDbContext>()
would be enough.我的印象是
AddEntityFrameworkStores<ApplicationDbContext>()
就足够了。
You are an async void
victim: 你是一个
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");
}
You are dispatching an asynchronous operation that is not being awaited, and the context will be disposed before the await context.SaveChangesAsync()
in CreateAsync
. 您正在调度未等待的异步操作,并且上下文将在
CreateAsync
的await context.SaveChangesAsync()
之前CreateAsync
。
Fast, obvious solution: 快速,明显的解决方案
[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");
}
However, you should always return IActionResult
from an Action. 但是,您应始终从Action返回
IActionResult
。 That makes it easier to change the response code as well as show your intent: 这样可以更轻松地更改响应代码并显示您的意图:
[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);
}
}
I had same problem, I forgot add 2 row in my StartUp.cs:我有同样的问题,我忘记在我的 StartUp.cs 中添加 2 行:
services.AddScoped<UserManager, UserManager>(); services.AddScoped<UserManager, UserManager>();
services.AddScoped<RoleManager, RoleManager>(); services.AddScoped<RoleManager, RoleManager>();
Add it, it will work normally!添加它,它会正常工作!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.