Have a many to many relationship between users and posts. I want to create new values in the post table and the association table with postID and logged in user's ID. No error message and it looks like I can create a post when I run the application but nothing is saved in any table. I can see when I run debug it goes all the steps, even save to the database. What's wrong?
Post model
public class Post
{
public Post()
{
this.ApplicationUser = new HashSet<ApplicationUser>();
}
public int PostId { get; set; }
public string Message { get; set; }
public DateTime MessageDate { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
IdentityModels
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public ApplicationUser()
{
this.Posts = new HashSet<Post>();
}
public virtual ICollection<Post> Posts { get; set; }
}
And my create function to create a new post
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PostId,Message,MessageDate")] Post post)
{
var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var userId = User.Identity.GetUserId();
var user = manager.FindById(userId);
if (ModelState.IsValid)
{
user.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(post);
}
I have values in all the variables for the user (manager, userId, user) and three tables (Posts, AspNetUsers and ApplicationUserPost)
Update
Error when I try Attach (and solution from CodeNotFound).
Error 1 'System.Data.Entity.IDbSet' does not contain a definition for 'FindById' and no extension method 'FindById' accepting a first argument of type 'System.Data.Entity.IDbSet' could be found (are you missing a using directive or an assembly reference?)
Error 2 'FreePost.Models.ApplicationDbContext' does not contain a definition for 'Attach' and no extension method 'Attach' accepting a first argument of type 'FreePost.Models.ApplicationDbContext' could be found (are you missing a using directive or an assembly reference?)
The first error message is the reason I chose to use userManager.
It isn't working because your db.SaveChanges
does nothing. Your context does nothing because it know nothing about the Post
instance you're attempting to add.
To fix that you need to first attach the current instance of ApplicationUser
to the context like below:
var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var userId = User.Identity.GetUserId();
var user = manager.FindById(userId);
if (ModelState.IsValid)
{
// Line below you tell your DbContext to take care of ApplicationUser instance.
db.Users.Attach(user);
user.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}
Side notes: I will refactor your code like this:
if (ModelState.IsValid)
{
// Move your code that query the database here so you query your database only if the model is valid.
var userId = User.Identity.GetUserId();
// You don't need ApplicationUserManager instance to get the ApplicationUser instance.
// If your Post class have a UserId foreign key property then this line is uselesss.
// Just set the UserId property of Post class.
var user = db.Users.Find(userId);
user.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}