在UserManager.ResetPasswordAsync上c# – ‘无法访问已处置对象’错误
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了在UserManager.ResetPasswordAsync上c# – ‘无法访问已处置对象’错误,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3255字,纯文字阅读大概需要5分钟。
内容图文
![在UserManager.ResetPasswordAsync上c# – ‘无法访问已处置对象’错误](/upload/InfoBanner/zyjiaocheng/788/0c0c9a111c8d48168a73d08d0eb99643.jpg)
执行userManager.ResetPasswordAsync时出现以下错误:
An unhandled exception occurred while processing the request.
ObjectDisposedException: Cannot access a disposed object.
Object name: 'TestDb'.
Microsoft.Data.Entity.DbContext.get_ServiceProvider()
我简化了代码,以便更容易阅读.我在控制器生命周期中调用了userManager两次.一旦生成令牌,一次用于重置密码:
private readonly UserManager<ApplicationUser> userManager;
// controller's constructor
public AuthController(UserManager<ApplicationUser> userManager) {
this.userManager = userManager;
}
[AllowAnonymous, HttpPost]
public async Task<ActionResult> ForgotPass(ForgotPassViewModel model) {
//model checks
var user = new UserQuery(db).GetUserByUserName(model.UserName);
//check if user exists
var token = await userManager.GeneratePasswordResetTokenAsync(user);
var url = $"{config.Url}/auth/resetpass?user={user.Id}&token={WebUtility.UrlEncode(token)}";
// send email with the reset url
model.Success = "An email has been sent to your email address";
return View(model);
}
[AllowAnonymous, HttpPost]
public async Task<ActionResult> ResetPass(ResetPassViewModel model) {
//model checks
var user = new UserQuery(db).GetUserById(model.UserId);
//error occurs here:
var result = await userManager.ResetPasswordAsync(user, model.Token, model.Password);
//check result
model.Success = "Password successfully reset";
return View(model);
}
后来编辑:
这是UserQuery的一个函数(如下面的评论中所要求的).我确实使用’using’包装器:
public ApplicationUser GetUserByUserName(string userName) {
using (var db = this.dbContext) {
var user = (from u in db.Users
where u.UserName == userName
select u).SingleOrDefault();
return user;
}
}
解决方法:
使用构造是围绕a的语法糖
DbContext context = null;
try
{
context = new DbContext();
...stuff inside the using block ...
}
finally
{
if(context!=null)
context.Dispose()
}
这和打电话一样
using(DbContext context = new DbContext())
{
...stuff inside the using block ...
}
块.这样可以确保尽快处理对象,即使发生异常(最后总是调用块).
ASP.NET Core中的DbContext(特别是它的ASP.NET核心身份注册)注册为作用域生命周期,这意味着在一个请求的持续时间内将返回相同的引用.
但是当你在请求结束之前过早地处理它(使用块或者自己调用.Dispose()方法)时,当另一个方法试图访问它时它会爆炸.
有条件的生命周期是推荐的生命周期,因为DbContext在生存时间很长时会占用大量内存,因为DbContext会跟踪所有记录的更改,直到您将其丢弃为止.
因此,在没有依赖注入或简单教程的传统应用程序中,您可以使用new创建它并尽快处理它.但是在Web应用程序中,请求非常短暂,并且在大多数情况下都可以使用范围的生命周期.可能存在一些极端情况,其中瞬态(ASP.NET Core IoC容器中的AddTransient方法)生命周期更好.
如果你真的需要瞬态解析,你可以创建一个工厂方法并将其注入你的服务,例如:
services.AddTransient<Func<MyDbContext>>( (provider) => new Func<MyDbContext>( () => new MyDbContext()));
并将其注入您的服务/控制器:
public class MyService
{
public readonly Func<MyDbContext> createMyContext;
public MyService(Func<MyDbContext> contextFactory)
{
this.createContext = contextFactory;
}
public User GetUserById(Guid userId)
{
// note we're calling the delegate here which
// creates a new instance every time
using(var context = createContext())
{
return context.User.FirstOrDefault(u => u.Id = userId);
}
}
}
这不会导致问题,但比必要的更复杂.如果您需要事务,这可能不会很好,因为事务是每个DbContext实例,而Identity将始终使用范围的事务
内容总结
以上是互联网集市为您收集整理的在UserManager.ResetPasswordAsync上c# – ‘无法访问已处置对象’错误全部内容,希望文章能够帮你解决在UserManager.ResetPasswordAsync上c# – ‘无法访问已处置对象’错误所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。