C
C#5mo ago
ARK

Display many-to-many table data using view model in controller in ASP.NET Core MVC

I want to display many-to-many table data using a view model in controller but I get this error:
CS0029: Cannot implicitly convert type 'Website.Model.PostModel' to 'System.Collections.GenericList<Website.Model.PostModel>'
Model:
c#
public class PostModel
{
[Key]
public int Id { get; set; }

public List<TagsModel> Tags { get; set; } = new List<TagsModel>();

public virtual List<PostTagModel> PostTags { get; set; } = new List<PostTagModel>();
}

public class TagsModel
{
[Key]
public int Id { get; set; }

public List<PostModel> Posts { get; set; }
public virtual List<PostTagModel> PostTags { get; set; }
}

public class PostTagModel
{
public int PostId { get; set; }
public int TagId { get; set; }

public virtual PostModel Post { get; set; }
public virtual TagsModel Tag { get; set; }
}
c#
public class PostModel
{
[Key]
public int Id { get; set; }

public List<TagsModel> Tags { get; set; } = new List<TagsModel>();

public virtual List<PostTagModel> PostTags { get; set; } = new List<PostTagModel>();
}

public class TagsModel
{
[Key]
public int Id { get; set; }

public List<PostModel> Posts { get; set; }
public virtual List<PostTagModel> PostTags { get; set; }
}

public class PostTagModel
{
public int PostId { get; set; }
public int TagId { get; set; }

public virtual PostModel Post { get; set; }
public virtual TagsModel Tag { get; set; }
}
ViewModel:
c#
public class CardsViewModel
{
public List<PostModel>? PostCard { get; set; }
}
c#
public class CardsViewModel
{
public List<PostModel>? PostCard { get; set; }
}
Controller:
c#
[HttpGet]
public async Task<IActionResult> Detail(int id)
{
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.SingleAsync(t => t.Id == id);
};

return View(TaggedPostVM);
}
c#
[HttpGet]
public async Task<IActionResult> Detail(int id)
{
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.SingleAsync(t => t.Id == id);
};

return View(TaggedPostVM);
}
View:
@using RecipeWebsite.ViewModels.CardsViewModel

@model CardsViewModel

@foreach (var item in Model.PostCard)
{
<!-- HTML -->
}
@using RecipeWebsite.ViewModels.CardsViewModel

@model CardsViewModel

@foreach (var item in Model.PostCard)
{
<!-- HTML -->
}
When the controller is used without view model, it works without error. Example:
c#
[HttpGet]
public async Task<IActionResult> Detail(int id)
{
var Tag = await _context.Posts
.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.SingleAsync(t => t.Id == id);

return View(Tag);
}
c#
[HttpGet]
public async Task<IActionResult> Detail(int id)
{
var Tag = await _context.Posts
.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.SingleAsync(t => t.Id == id);

return View(Tag);
}
7 Replies
z0mb
z0mb5mo ago
You defined PostCard on your view model as being a List<PostModel>? But you are trying to assign the value to a single PostModel element when you use the .SingleAsync method in your controller.
ARK
ARK5mo ago
@z0mb I tried using .ToListAsync() method but the code gives error regardless. Here is what I tried:
c#
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.ThenInclude(t => t.Id == id)
.ToListAsync()
};
c#
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.ThenInclude(t => t.Id == id)
.ToListAsync()
};
or
c#
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.Where(t => t.Id == id)
.ToListAsync()
};
c#
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.ThenInclude(p => p.Post)
.Where(t => t.Id == id)
.ToListAsync()
};
They give server errors!
z0mb
z0mb5mo ago
As in it's blowing up when you run the app? What's the exception? Try wrapping your logic in a try catch block and logging the exception Sounds like the compile issue was solved, so that's some progress.
ARK
ARK5mo ago
I apologize, but I don't know to use try catch block. The exceptions only appear when I try to open the specific page. Here are the exceptions: When using .ThenInclude().ThenInclude().ToListAsync():
InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Query.NavigationBaseIncludeIgnored': The navigation 'PostTagModel.Post' was ignored from 'Include' in the query since the fix-up will automatically populate it. If any further navigations are specified in 'Include' afterwards then they will be ignored. Walking back include tree is not allowed. This exception can be suppressed or logged by passing event ID 'CoreEventId.NavigationBaseIncludeIgnored' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
When using .ThenInclude().Where().ToListAsync():
InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Query.NavigationBaseIncludeIgnored': The navigation 'PostTagModel.Post' was ignored from 'Include' in the query since the fix-up will automatically populate it. If any further navigations are specified in 'Include' afterwards then they will be ignored. Walking back include tree is not allowed. This exception can be suppressed or logged by passing event ID 'CoreEventId.NavigationBaseIncludeIgnored' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
z0mb
z0mb5mo ago
On mobile, but I can teach you how to use try catch blocks tomorrow when I'm around my PC if nobody else does before then. To get you going, get rid of your theninclude(), but keep your first .include(), .where() and .tolistasync() pieces. See how that does. I will say, typically you would actually map the results of the EF query to a DTO and use them, instead of returning the tracked items to your view. But that's another topic.
ARK
ARK5mo ago
Thank you
z0mb
z0mb5mo ago
I made an edit to that, stating to keep your first .include. Get rid of the .theninclude portion
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.Where(t => t.Id == id)
.ToListAsync()
};
var TaggedPostVM = new CardsViewModel
{
PostCard = await _context.Posts.Include(t => t.PostTags)
.Where(t => t.Id == id)
.ToListAsync()
};