I am creating tags for my website posts using Many-to-Many relationship. I managed to create PostTags database table using Entity Framework following the Microsoft Documentation.
I now want to insert tag data in database using Controller and ViewModel, when creating the post, but have no idea how to proceed.
My Code and what I have Tried-
Models:
public class PostModel
{
[Key]
public int Id { get; set; }
public string? Title { get; set; }
public List<TagModel> Tags { get; set; }
public List<PostTagModel> PostTags { get; set; }
}
public class TagModel
{
[Key]
public int Id { get; set; }
public string? Title { get; set; }
public List<PostModel> Posts { get; set; }
public List<PostTagModel> PostTags { get; set; }
}
public class PostTagModel
{
public int PostId { get; set; }
public int TagId { get; set; }
public PostModel Post { get; set; }
public TagModel Tag { get; set; }
}
DatabaseContext.cs:
public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
{
}
public DbSet<PostModel> Posts { get; set; }
public DbSet<TagModel> Tags { get; set; }
public DbSet<PostTagModel> PostTags { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PostModel>()
.HasMany(e => e.Tags)
.WithMany(e => e.Posts)
.UsingEntity<PostTagModel>();
}
}
ViewModel:
public class CreatePostViewModel
{
public string? Title { get; set; }
public int? TagId { get; set; }
public List<TagModel> TagList { get; set; }
}
Controller:
CS0029: Cannot implicitly convert type 'int?' to 'System.Collections.GenericList<Website.Model.TagModel>
[HttpGet]
public IActionResult Create()
{
// Tags initialization for view
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreatePostViewModel postVM)
{
if (ModelState.IsValid)
{
var post = new PostModel
{
Title = postVM.Title,
Tags = postVM.TagId // CS0029 : cannot implicitly convert type 'int?' to 'System.Collections.GenericList<Website.Model.TagModel>
};
_postInterface.Add(post);
return RedirectToAction("Index");
}
else
{
// Error
}
return View(postVM);
}
View:
@using SimpleWebsite.ViewModels.PostViewModel
@model CreatePostViewModel
<!-- Code above -->
<!-- Tag -->
<div class="col-md-12 mb-3">
<label asp-for="TagId" class="control-label"></label>
<div class="form-check-inline">
@foreach (var item in Model.TagList)
{
<input type="checkbox" class="btn-check" id="@item.Id" value="@item.Id">
<label asp-for="TagId" class="btn btn-outline-primary" for="@item.Id">@item.Title</label>
}
</div>
<span asp-validation-for="TagId" class="text-danger"></span>
</div>
<!-- Code Below -->
I doubt that you can pass the
TagIdvalue to the controller as the checkbox needs to have thenameattribute:name="TagId".Note that, with the loop, user can check for multiple checkboxes and would suggest to change the
TagIdproperty toTagIdswith anint[]?type.In your controller, you have to retrieve the
Tagdata from the database and filter based on user-selectedTagIds. And insert thepostwith theselectedTags.