我在我的MVC5应用程序中使用了以下HttpPost
Delete()方法。据我所知,与此控制器,视图甚至模型无关的任何内容都已更改。
// 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 Pieces:
[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()代码完全符合预期。
修改:
Startup.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 /中的Startup.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);
感谢所有花时间协助的人!
答案 0 :(得分:4)
问题是您实际上在这里使用了2 DbContext
,他们无法跟踪彼此的实体。
您必须更改您的Controller代码,以使db
和UserManager
共享相同的上下文实例引用:
public UserManagementController()
{
this.db = context.Get<ApplicationDbContext>();
}