C
C#2y ago
framoz

ASP NET MVC, can't show Collection in View, VS say it is null

Hello, I'm working on a MVC Project for a film website (IMDb like). I have a User class and a Person class with a many to many relationship and want to show a User table in this Person detail view.
*@ This is the code inside the cshtml, that I tried using to show the data in the view
<table class="table table-bordered table table-striped" style="width:100%">
<thead>
<tr>
<th>
Users
</th>
</tr>
</thead>
<tbody>
@if (Model != null && Model.Users != null)
{
@foreach (var obj in Model.Users)
{
<tr>
<td>
@obj.Name
</td>

</tr>
}
}
</tbody>
</table>
*@ This is the code inside the cshtml, that I tried using to show the data in the view
<table class="table table-bordered table table-striped" style="width:100%">
<thead>
<tr>
<th>
Users
</th>
</tr>
</thead>
<tbody>
@if (Model != null && Model.Users != null)
{
@foreach (var obj in Model.Users)
{
<tr>
<td>
@obj.Name
</td>

</tr>
}
}
</tbody>
</table>
33 Replies
framoz
framoz2y ago
User and Person class is like shown bellow:
public class User
{
// [Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }

public ICollection<Review> Reviews { get; set; }
// public ICollection<Film> Watched { get; set; }
public ICollection<Film> Films { get; set; }
public ICollection<Person> People { get; set; }
}

public class Person
{
// [Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime Birthdate { get; set; }

[ValidateNever]
public ICollection<Film> Films { get; set; }
[ValidateNever]
public ICollection<User> Users { get; set; }
}
public class User
{
// [Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }

public ICollection<Review> Reviews { get; set; }
// public ICollection<Film> Watched { get; set; }
public ICollection<Film> Films { get; set; }
public ICollection<Person> People { get; set; }
}

public class Person
{
// [Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime Birthdate { get; set; }

[ValidateNever]
public ICollection<Film> Films { get; set; }
[ValidateNever]
public ICollection<User> Users { get; set; }
}
Inside my DBContext I have this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<User>()
.HasMany(u => u.People)
.WithMany(p => p.Users)
.UsingEntity(j => j.ToTable("UserPeople"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<User>()
.HasMany(u => u.People)
.WithMany(p => p.Users)
.UsingEntity(j => j.ToTable("UserPeople"));
}
I really don't know where else to search or what to do to correct this I'm pretty sure my DB is ok and I made the relation correctly, but I simply can't make this work. I created some users and persons in my db and created the relation between those in an intermediary table "UserPeople" that was created by the modelBuilder
ladyhail
ladyhail2y ago
Looks like the Model is not passed to the View. Please share Controller code.
framoz
framoz2y ago
@LadyHail thank you for answering, here is the controller code for the view.
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.People == null)
{
return NotFound();
}

var person = await _context.People
.FirstOrDefaultAsync(m => m.Id == id);
if (person == null)
{
return NotFound();
}

return View(person);
}
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.People == null)
{
return NotFound();
}

var person = await _context.People
.FirstOrDefaultAsync(m => m.Id == id);
if (person == null)
{
return NotFound();
}

return View(person);
}
ladyhail
ladyhail2y ago
In View you need to specify Model type like this: @model Namespace.Person
framoz
framoz2y ago
I think it was already specified :/
ladyhail
ladyhail2y ago
I suggest debugging what's inside person before returning
framoz
framoz2y ago
apparently the User collection inside Person is null when I debug it, but according to the DB, it should not be. Person1 should have 3 users there
framoz
framoz2y ago
i know these questions may sound a bit dumb, is just that this is my first "serious" project, and I'm kind of lost in some parts of it. Mainly because I don't know what to search to learn what is wrong
ladyhail
ladyhail2y ago
Is it Entity Framework Core?
framoz
framoz2y ago
yes
ladyhail
ladyhail2y ago
I think you can find it useful. The relationship needs to be specified via intermediate table. https://www.entityframeworktutorial.net/efcore/configure-many-to-many-relationship-in-ef-core.aspx
Configure Many-to-Many Relationships in Entity Framework Core
Learn how to configure a many-to-many relationship using Fluent API in Entity Framework Core.
framoz
framoz2y ago
I had an intermediate table before, and it was giving me the same error I tried deleting it and making the relation in a different way (this way), but that didn't fixed it :/ I'll make the intermediate table again and try it!
framoz
framoz2y ago
framoz
framoz2y ago
same thing 😭 I created the intermediate one, dropped my DB, made a new one
public class PeopleUsers
{

public int UserId { get; set; }
public int PersonId { get; set; }

public User User { get; set; }
public Person Person { get; set; }
}
public class PeopleUsers
{

public int UserId { get; set; }
public int PersonId { get; set; }

public User User { get; set; }
public Person Person { get; set; }
}
public class Person
{
// [Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime Birthdate { get; set; }

[ValidateNever]
public ICollection<Film> Films { get; set; }
[ValidateNever]
public ICollection<PeopleUsers> PeopleUsers { get; set; }
}


public class User
{
// [Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }

public ICollection<Review> Reviews { get; set; }
// public ICollection<Film> Watched { get; set; }
public ICollection<Film> Films { get; set; }
public ICollection<PeopleUsers> PeopleUsers { get; set; }
}
public class Person
{
// [Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime Birthdate { get; set; }

[ValidateNever]
public ICollection<Film> Films { get; set; }
[ValidateNever]
public ICollection<PeopleUsers> PeopleUsers { get; set; }
}


public class User
{
// [Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }

public ICollection<Review> Reviews { get; set; }
// public ICollection<Film> Watched { get; set; }
public ICollection<Film> Films { get; set; }
public ICollection<PeopleUsers> PeopleUsers { get; set; }
}
DBContexto
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
////Person-Favorite many-to-many relation for favorite person list in User and users that favorited a person in Person
modelBuilder.Entity<PeopleUsers>()
.HasKey(pf => new { pf.PersonId, pf.UserId });

modelBuilder.Entity<PeopleUsers>()
.HasOne(pf => pf.User)
.WithMany(u => u.PeopleUsers)
.HasForeignKey(pf => pf.UserId);

modelBuilder.Entity<PeopleUsers>()
.HasOne(pf => pf.Person)
.WithMany(p => p.PeopleUsers)
.HasForeignKey(pf => pf.PersonId);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
////Person-Favorite many-to-many relation for favorite person list in User and users that favorited a person in Person
modelBuilder.Entity<PeopleUsers>()
.HasKey(pf => new { pf.PersonId, pf.UserId });

modelBuilder.Entity<PeopleUsers>()
.HasOne(pf => pf.User)
.WithMany(u => u.PeopleUsers)
.HasForeignKey(pf => pf.UserId);

modelBuilder.Entity<PeopleUsers>()
.HasOne(pf => pf.Person)
.WithMany(p => p.PeopleUsers)
.HasForeignKey(pf => pf.PersonId);
ladyhail
ladyhail2y ago
The only difference I see is User -> Id. Following docs it should be UserId and same for person.
framoz
framoz2y ago
in the DBContext?
ladyhail
ladyhail2y ago
In class definition
framoz
framoz2y ago
In the collections or at the Intermediate class?
ladyhail
ladyhail2y ago
In the User class property Id rename to UserId
framoz
framoz2y ago
ok
ladyhail
ladyhail2y ago
Same for Person. Rename Id to PersonId. It shouldn't make a difference, but lets try.
framoz
framoz2y ago
well, it broke my code lol not building, and cant update db
ladyhail
ladyhail2y ago
You need to drop db and recreate
framoz
framoz2y ago
😭 😭 😭
framoz
framoz2y ago
I'll try again, just a minute I dropped it on MSSMS still cant update it is not building and it dont show me any errors too well, I restored to the last saved version the original one of the post isn't it possible that the error is just on the code in the cshtml?
ladyhail
ladyhail2y ago
You van try to debug cshtml. But if its null on Controller then it will be null im view
framoz
framoz2y ago
I was thinking if there is another way to write what I want to do inside that foreach
ladyhail
ladyhail2y ago
The syntax is valid. I'm pretty sure if you follow the tutorial it'll work
framoz
framoz2y ago
made all the changes, following the tutorial, still the same error
framoz
framoz2y ago
it says that PeopleUsers for this Person is null
ladyhail
ladyhail2y ago
One more idea - in controller before .FirstOrDefault add .Include(x => x.peopleUsers)
framoz
framoz2y ago
i'll try it IT WORKED, THANK YOU SO MUCH someone said something similar in the chat, but I couldnt get it to work you saved my life!
ladyhail
ladyhail2y ago
You're welcome