Reputation: 7818
I'm trying to display hierarchial data in my view - I have 2 models (parent/child linked)
Models:
public class Clinic
{
public int ClinicId { get; set; }
[Display(Name="Clinic Name")]
public string Name { get; set; }
public string Description { get; set; }
public List<Property> Properties { get; set; }
}
public class Property
{
public int PropertyID { get; set; }
public int ClinicId { get; set; }
[Display(Name="Property Address")]
public string Address { get; set; }
public Clinic Clinic { get; set; }
public List<Room> Rooms { get; set; }
}
public class Room
{
public int RoomId { get; set; }
public int PropertyId { get; set; }
public string RoomName { get; set; }
public Property Property { get; set; }
}
My controller is builds this Linq query - which displays fine in LinqPad:
//
// GET: /Property/Overview/
public ActionResult Overview()
{
// original code - replaced following help below
// var ovw =
// (from c in db.Clinics
// select new
// {
// c.Name,
// Properties =
// from p in db.Properties
// where p.ClinicId == c.ClinicId
// select new
// {
// p.Address
// }
// });
IEnumerable<Clinic> ovw = from c in db.Clinics
select c;
return View(ovw);
}
My view is:
@model IEnumerable<ttp.Models.Clinic>
@{
ViewBag.Title = "Overview";
}
<h2>Overview</h2>
@foreach (var item in Model) {
@item.Name
<br />
if (item.Properties != null){
foreach (var item2 in item.Properties) {
@item2.Address <br />
if (item2.Rooms != null){
foreach (var item3 in item2.Rooms) {
@item3.RoomName <br />
}
}
}
}
It should display:
Clinic1
Property1
Room1
Room2
Room3
Property2
Room4
Room5
Clinic2
Property3
Room6
....
But instead just shows:
Clinic1
Clinic2
Clinic3
This will only ever populate the first level of data of Clinics - not the child Properties, or the child Rooms of Properties.
Can anyone please help me fix my controller or my view?
Thanks, Mark
Upvotes: 1
Views: 1613
Reputation: 7818
I've plus 1'd the answers above, as they are very helpful - but the actual problem/answer was in my model definitions - to access the linked tables in the controller/view, I had to add VIRTUAL to the linked property:
Where I had:
public List<Property> Properties { get; set; }
That should have been:
public virtual ICollection<Property> Properties { get; set; }
I hope this helps someone else with this problem.
Thanks to Steve and Ufuk for your help, and time.
Mark
Upvotes: 0
Reputation: 38488
You should create instances of Clinic and Property classes. You are using anonymous types.
Also don't forget to call ToList() for Properties because your query will return IEnumerable<Property>
or IQueryable<Property>
.
IEnumerable<Clinic> ovw = from c in db.Clinics
select new Clinic
{
Name = c.Name,
Properties =(from p in db.Properties
where p.ClinicId == c.ClinicId
select new Property
{
Address = p.Address
}).ToList()
});
Upvotes: 4
Reputation: 2071
You're not actually returning a list of Clinics because you've used
select new { ... }
Instead you want to just get the clinics. The model and collection already exists. There's no need to recreate it:
var ovw = db.Clinics;
If you're trying to have a view model which is separate from the db model (which is good practice) look into AutoMapper or manually map from the db Clinic to a view model Clinic. Then instead of select new { ... } you would use
select new vmClinic { Name = c.Name, ... }
where vmClinic is your viewmodel clinic.
Upvotes: 2