I'm trying to create a 1 to many relationship between my recipe table and AspNet user table, but I end up with NULL as my foreign key whenever I create a new recipe.
public virtual ApplicationUser ApplicationUser { get; set; }
is in my Recipe model and
public List<Recipe> Recipes { get; set; }
is in my ApplicationUser model
Recipes table after i've added some test recipes in DbInitializer. Row 3 was created through localhost and the foreign key is NULL.
foreach (var u in db.Users.Include(b => b.Recipes) )
{
for (int i = 1; i < 3; i )
{
u.Recipes.Add(new Recipe
{
Title = $"{i}",
Introduction = $"{i}",
Ingredients = $"{i}",
Instructions = $"{i}",
Nutrients = $"{i}"
});
}
}
db.SaveChanges();
I just can't figure out how to set the foreign key in the Controller for when I create a new recipe :
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,Introduction,Ingredients,Instructions,Nutrients")] Recipe recipe)
{
if (ModelState.IsValid)
{
_context.Add(recipe);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(recipe);
}
Sorry if my post is messy, this is the first time I've posted here.
EDIT: I'm uncertain but is this what you asked for? I would access user id by just typing in user.Id right?
public class RecipesController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
public RecipesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
EDIT 2: Thanks for the help, the code correctly assigned a foreign key now.
public async Task<IActionResult> Create([Bind("Id,Title,Introduction,Ingredients,Instructions,Nutrients")] Recipe recipe)
{
if (ModelState.IsValid)
{
// Adding the foreign key to recipes
var user = await _userManager.GetUserAsync(User);
recipe.UserId = user.Id;
_context.Add(recipe);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(recipe);
}
CodePudding user response:
There are a number of ways to do this, I personally assign audit info inside the DbContext.SaveChanges()
method, but that's a global approach that's out of scope for this post.
At a fundamental level you need to assign the user before you call SaveChanges()
so the following code might work in your case:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,Introduction,Ingredients,Instructions,Nutrients")] Recipe recipe)
{
if (ModelState.IsValid)
{
// assign the user
var user = await _userManager.GetUserAsync(User);
recipe.ApplicationUser = user;
_context.Add(recipe);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(recipe);
}
NOTE: This is just a guide, in some cases the above assignment may not work, especially if your
UserManager
does not use the saveDbContext
instance. In such a case you will find it simpler to assign the user using the Foreign Key, not the navigation property.