Reputation: 4966
I have a strongly typed view which displays students from a database table "Student_A"
View:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Student.Models.Student_A>>" %>
<table>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.Encode(item.StudentName) %>
</td>
<td>
<%= Html.Encode(item.StudentId) %>
</td>
</tr>
<% } %>
</table>
Controller:
public ActionResult ShowStudents()
{
ViewData.Model = stud.Student_A.Where(a => a.StudentId != 0);
return View();
}
I have another table "Student_B" which stores students as well, I would like to display this students in my view as well. Something like:
public ActionResult ShowAllStudents()
{
var StudentA = stud.Student_A.Where(a => a.StudentId != 0);
var StudentB = stud.Student_B.Where(a => a.StudentId != 0);
ViewData.Model = StudentA + StudentB;
return View();
}
Is it possible to show data from two different tables in a strongly typed view in a single controller action? Or will I have to create a database view that displays students from "Student_A" and "Student_B" tables and then display them in a view?
Any help is much appreciated
Upvotes: 3
Views: 989
Reputation: 16928
I had to do something similar for a Treeview instead of a table and needed to combine two different collections in order to generate a treeview from a single collection. In my case I was able to combine them using this...
var allStudents = StudentA.Union((IEnumerable<Object>)StudentB);
Then in your code when you iterate through each object in the collection you can test the datatype of the object and display it how you want, in case you want to use different code to render different types of students. I needed to do this because in my case a node that had child items was a completely different type than the node without child items.
Note that by using Object as your root collection type instead of some sort of shared inheritance (an interface for example) you'll have no way to sort your combined collection or filter them.
If you need to mix the two collections rather than just appending one to the end of the other, you'll have to use some sort of shared inheritance.
UPDATE:
Sample code to show that this works. I tested in LinqPad, but I'm sure it'd work just as well in Visual Studio.
public class Student_A
{
public int Id{get;set;}
public string FirstName{get;set;}
public string LastName{get;set;}
}
public class Student_B
{
public int Id{get;set;}
public string FirstName{get;set;}
public string MiddleName{get;set;}
public string LastName{get;set;}
}
void Main()
{
List<Student_A> StudentAs = new List<Student_A>();
StudentAs.Add(new Student_A(){Id = 1, FirstName = "Jack", LastName = "Smith"});
StudentAs.Add(new Student_A(){Id = 3, FirstName = "Sarah", LastName = "Jane"});
StudentAs.Add(new Student_A(){Id = 7, FirstName = "Zack", LastName = "Hall"});
List<Student_B> StudentBs = new List<Student_B>();
StudentBs.Add(new Student_B(){Id = 2, FirstName = "Jane", MiddleName = "T.", LastName = "Kelly"});
StudentBs.Add(new Student_B(){Id = 9, FirstName = "Rose", MiddleName = "Marie", LastName = "Tyler"});
StudentBs.Add(new Student_B(){Id = 4, FirstName = "Bobby", MiddleName = "Stephen", LastName = "Singer"});
var result = StudentAs.Union((IEnumerable<Object>)StudentBs);
result.Dump();
}
Upvotes: 0
Reputation: 20674
You can create a view model with both
public class StudentsViewModel
{
public List<Student.Models.Student_A> StudentsA {get;set}
public List<Student.Models.Student_B> StudentsA {get;set}
}
and return this in your view, if indeed the A and B students have different fields
var viewModel = new StudentsViewModel();
viewModel.StudentsA = stud.Student_A.Where(a => a.StudentId != 0);
viewModel.StudentsB = stud.Student_B.Where(a => a.StudentId != 0);
return View(viewModel);
Upvotes: 1
Reputation: 9763
you need to store the resutls in an "agnostic" way. For example
public class StudentInfo
{
public string Type { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
var students = stud.Student_A.Where(...).Select(a => new StudentInfo { Type = "Student_A", FirstName = a.FirstName, LastName = a.LastName });
students.concat( stud.Student_B.Where(...).Select(b => new StudentInfo { Type = "Student_B", FirstName = b.FirstName, LastName = b.LastName });
ViewData.Model = students;
return View();
By doing this, you have a common class of student info to store common properties which can be used as a strongly-typed model.
Alternatively, if you want to list them SEPARATELY, you could create a composite ViewModel
public class StudentsVM
{
public IEnumerable<Student_A> Student_A { get; set; }
public IEnumerable<Student_B> Student_B { get; set; }
}
var vm = new StudentsVM;
vm.Student_A = stud.Student_A.Where(...);
vm.Student_B = stud.STudent_B.Where(...);
ViewData.Model = vm;
Upvotes: 2