MVC5/EF6:无法删除对象,因为在ObjectStateManager中找不到该对象
本文关键字:对象 因为 ObjectStateManager 找不到 MVC5 EF6 删除 | 更新日期: 2023-09-27 18:09:06
我有以下HttpPost
Delete((方法,该方法在我的MVC5应用程序中运行。据我所知,与此控制器、视图甚至模型相关的内容均未更改。
// POST: Admin/UserManagement/Delete/5
[HttpPost, ActionName("DeleteConfirmed")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(string id)
{
ApplicationUser applicationUser = db.Users.Find(id);
if (applicationUser == null)
{
ModelState.AddModelError("", "Failed to find User ID for deletion.");
}
else
{
IdentityResult result = await UserManager.DeleteAsync(applicationUser);
if (result.Succeeded)
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
else
{
ModelState.AddModelError("", "Failed to Delete User.");
var errors = string.Join(",", result.Errors);
ModelState.AddModelError("", errors);
}
}
return View(applicationUser);
}
UserManager工件:
[CustomAuthorization(myRoles = "Admin")]
public class UserManagementController : Controller
{
protected ApplicationDbContext db { get; set; }
private ApplicationUserManager _userManager;
public UserManagementController()
{
this.db = new ApplicationDbContext();
}
public UserManagementController(ApplicationUserManager userManager)
{
UserManager = userManager;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
当我的代码到达IdentityResult result = await UserManager.DeleteAsync(applicationUser)
时,它立即跳到下面的Dispose((方法,并且没有加载索引视图,而是给出:Server Error in '/' Application.
The object cannot be deleted because it was not found in the ObjectStateManager.
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
if (UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
}
base.Dispose(disposing);
}
有人能告诉我哪里出了问题吗?我以前从未见过这种错误。以前,这个DeleteConfirmed((代码完全按照预期工作。
编辑:
启动.cs:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(PROJECT.Startup))]
namespace PROJECT
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
EDIT2:
CustomAuthorization.cs(Helper(:
public class CustomAuthorization : AuthorizeAttribute
{
public string myRoles { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
var userAuthInfo = HttpContext.Current.User;
if (userAuthInfo != null)
{
if (!userAuthInfo.Identity.IsAuthenticated)
{
string returnUrl = filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult("/Account/Login?returnUrl=returnUrl");
return;
}
string[] roles = myRoles.Split(',');
var userAuth = false;
foreach (string role in roles)
{
if (userAuthInfo.IsInRole(role))
{
userAuth = true;
break;
}
}
if (!userAuth)
{
var result = new RedirectResult("/Home?auth=0");
filterContext.Result = result;
}
}
}
}
EDIT3
启动。/App_Start/中的Auth.cs:
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
解决方案正如haim770所指出的,我在DeleteConfirmed()
操作方法中错误地使用了2个DbContext引用。
将ApplicationUser applicationUser = db.Users.Find(id)
更改为async
,一切正常:ApplicationUser applicationUser = await UserManager.FindByIdAsync(id);
感谢所有花时间提供帮助的人!
问题是您实际上在这里使用了2个DbContext
,它们无法跟踪彼此的实体。
您必须更改控制器代码,使db
和UserManager
共享相同的上下文实例引用:
public UserManagementController()
{
this.db = context.Get<ApplicationDbContext>();
}