Premise:
I'm trying to use a very simplified .net 6 MVC project to gain understanding of how to code ViewModels.
Thumbnail of Project
Models A B C (Joining Class)
ViewModel AB
**GitHub **
Environment: Net Core 6 MVC, Visual Studio Community 2022 (64 bit), WIndows 11
Please: whenever possible, provide help in the form of actual code - preferably changes to the code I've provided (a fair amount of time and effort goes into providing this code as the premise for the question) - or in example(s) of code you provide, in either case, in the format / syntax the code needs to be in to make the project. Abstraction, more often than not, obfuscates the answer.
Question
Why does data from the first property display but not from the second property? How do I change the controller action method code (below) to also display data from the second property?
Controller Action Method displays successfully as pictured (above)
//GET: AB
public IActionResult AB2()
{
//define a variable to store the return data.
var ab2 = new List<AB>();
//query A and B table,
var Alist = _context.A.ToList();
var Blist = _context.B.ToList();
//use foreach statement to filter data. And Add A and B to the ab list.
foreach (var item in Alist)
{
var newab = new AB()
{
A = item
};
//add the new item into the list.
ab2.Add(newab);
}
return View(ab2); // return the list to the view page.
}
**Full Code **
Models
A
namespace ViewModel.Models
{
public class A
{
public int Id { get; set; }
public string? One { get; set; }
public string? Two { get; set; }
public string? Three { get; set; }
public IEnumerable<C>? C { get; set; }
}
}
B
namespace ViewModel.Models
{
public class B
{
public int Id { get; set; }
public string? One { get; set; }
public string? Two { get; set; }
public string? Three { get; set; }
public IEnumerable<C>? C { get; set; }
}
}
C
using System.Security.Cryptography.Xml;
namespace ViewModel.Models
{
public class C
{
public int Id { get; set; }
public int AId { get; set; }
public int BId { get; set; }
// _______________________________________
public A? A { get; set; }
public B? B { get; set; }
}
}
Context
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ViewModel.Models;
namespace ViewModel.Data
{
public class ViewModelContext : DbContext
{
public ViewModelContext (DbContextOptions<ViewModelContext> options)
: base(options)
{
}
public DbSet<ViewModel.Models.A> A { get; set; } = default!;
public DbSet<ViewModel.Models.B>? B { get; set; }
public DbSet<ViewModel.Models.C>? C { get; set; }
}
}
ViewModel
using System.Security.Cryptography.Xml;
namespace ViewModel.Models.View
{
public class AB
{
public A? A { get; set; }
public B? B { get; set; }
}
}
View
@model IEnumerable<ViewModel.Models.View.AB>
@{
ViewData["AB2"] = "AB2";
}
<h1>AB2</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Property Set A, Property @Html.DisplayNameFor(model => model.A.One)
</th>
<th>
Property Set B, Property @Html.DisplayNameFor(model => model.B.One)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.A.One)
</td>
<td>
@Html.DisplayFor(modelItem => item.B.One)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.A.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.A.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.A.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
I created simplified project to use as a premise for this question. I have a working view derived through a viewmodel that includes a property from each of two classes. My question is now about a second view, coded in the controller differently from the first that displays a property from one class. I'm trying to get a second property from a second class to display.
I've tried a few changes to the controller action method code. Both failed:
//GET: AB
public IActionResult AB2()
{
//define a variable to store the return data.
var ab2 = new List<AB>();
//query A and B table,
var Alist = _context.A.ToList();
var Blist = _context.B.ToList();
//use foreach statement to filter data. And Add A and B to the ab list.
foreach (var item in Alist)
{
var newab = new AB()
{
A = item
//B = item **2nd change: did not work**
};
//add the new item into the list.
ab2.Add(newab);
}
//foreach (var item in Blist) **1st change: did not work**
//{
// var newab = new AB()
// {
// B = item
// };
// //add the new item into the list.
// ab2.Add(newab);
//}
return View(ab2); // return the list to the view page.
}

