Reputation: 115
I need to have a view that displays Employee First and Last Name and the Employees associated Supervisor First and Last name.
I have 2 models they are as follow:
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Department { get; set; }
public int SupervisorID { get; set; }
public virtual ICollection<Supervisor> Supervisor { get; set; }
}
public class Supervisor
{
public int SupervisorID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Department { get; set; }
public virtual Employee Employee { get; set; }
}
To display the needed data I have created another model:
public class EmployeeSupervisor
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Department { get; set; }
public string SupFirstName { get; set; }
public string SupLastName { get; set; }
public string SupPhone { get; set; }
public string SuoEmail { get; set; }
public string SupDepartment { get; set; }
}
and in the details action of a controller I do the following:
Employee employee = db.Employees.Find(id);
Supervisor supervisor = db.Supervisors.Find(employee.SupervisorID);
EmployeeSupervisor es = new EmployeeSupervisor
{
EmployeeID = employee.EmployeeID,
Department = employee.Department,
FirstName = employee.FirstName,
LastName = employee.LastName,
SupFirstName = supervisor.FirstName,
SupLastName = supervisor.LastName,
SuoEmail = supervisor.Email,
SupPhone = supervisor.Phone,
SupDepartment = supervisor.Department
};
return View(es);
Then in the view I have
@model TimeOffV3.Models.EmployeeSupervisor
and then lastly I do the following in the view
@Html.DisplayFor(model => model.FirstName)
@Html.DisplayFor(model => model.LastName)
@Html.DisplayFor(model => model.SupFirstName)
@Html.DisplayFor(model => model.SupLastName)
When I accomplish this task as described above with the EmployeeSupervisor model class, entity framework creates a corresponding table for EmployeeSupervisor in the database (as expected). This leads me to believe I'm doing it the wrong way as I can't imagine everytime I want to display data from 2 different models I need to create a new corresponding model and table.
Is the way I accomplished this correct? Should I be able to access the supervisor information using the navigation property defined in the Employee class? Can I pass in multiple models so I don't have to create a model containing the info from 2 separate models?
Upvotes: 2
Views: 6815
Reputation: 1456
To answer your question
Is the way I accomplished this correct?
No, what you are looking for is View Models. Rachel Appel has an excellent post regarding this that I strongly recommend you read - Use ViewModels to manage data & organize code in ASP.NET MVC applications.
What are View Models?
ViewModels allow you to shape multiple entities from one or more data models (in your case this would be Employee and Supervisor) or sources into a single object, optimized for consumption and rendering by the view. - Rachel Appel
In other words it's just another simple class just like Employee and Supervisor often referred to as a POCO.
public class EmployeeSupervisorViewModel
{
public int EmployeeId { get; set; }
public string Department { get; set; }
public string FristName { get; set; }
public string LastName { get; set; }
public string SupFirstName { get; set; }
public string SupLastName { get; set; }
public string SupEmail { get; set; }
public string SupPhone { get; set; }
}
This allows you to do the following in your Controller
var employee = _db.Employee.Find(id);
var supervisor = _db.Supervisor.Find(employee.SupervisorID);
var model = new EmployeeSupervisorViewModel()
{
EmployeeId = employee.EmployeeId,
Department = employee.Department,
FristName = employee.FirstName,
LastName = employee.LastName,
SupFirstName = supervisor.FirstName,
SupLastName = supervisor.LastName,
SupEmail = supervisor.Email,
SupPhone = supervisor.Phone
};
return View(model);
In your View simply accept the View Model, EmployeeSupervisorViewModel, as the model and operate on it as before.
@model TimeOffV3.Models.EmployeeSupervisorViewModel
In the long run this mapping can be a bit tedious with larger View Models. This is where AutoMapper comes in handy.
Lastly I'd also recommend reading this post from Jimmy Bogard (How we do MVC – View models) it has some really good points on how to do View Models such as having a 1:1 mapping of the View and View Model and more.
Upvotes: 1
Reputation: 8781
Indeed view receive only one model but this model doesn't have to be flat. Your view model could contain separate properties for each one of the entities
public class EmployeeSupervisor
{
public Employee Employee { get; set; }
public Supervisor Supervisor{ get; set; }
}
And in your view you work with them as following:
@Html.DisplayFor(model => model.Employee.FirstName)
@Html.DisplayFor(model => model.Employee.LastName)
@Html.DisplayFor(model => model.Supervisor.FirstName)
@Html.DisplayFor(model => model.Supervisor.LastName)
Additional thing that you should know, is that Views don't have to work with entities (those that have corresponding tables in the database). You can create a ViewModels that will contain only the properties that are used in your view. There are some libraries that can help you with mapping between ViewModels and entities, for example Automapper or ValueInjecter
If for example you need to display in your view only full names of employee and supervisor your view model could look like:
public class EmployeeSupervisorViewModel
{
public string EmployeeName { get; set; }
public string SupervisorName { get; set; }
}
And the controller:
Employee employee = db.Employees.Find(id);
Supervisor supervisor = db.Supervisors.Find(employee.SupervisorID);
var model = new EmployeeSupervisorViewModel
{
EmployeeName = string.Format("{0} {1}",employee.FirstName, employee.LastName),
SupervisorName = string.Format("{0} {1}",supervisor.FirstName, supervisor.LastName),
};
return View(model);
EmployeeSupervisorViewModel
is not an entity and should not have a database table It is used only on View/Controller level and contains only the information that is required by View (info that you want to render to the client)
Upvotes: 6
Reputation: 10818
Look into ViewModels.
You have the right idea, but the problem is you shouldn't be creating another table with that view model.
Make sure your EmployeeSupervisor
class is outside of your Entity Framework stuff, this class is strictly there to display data that corresponds to a view.
Upvotes: 2
Reputation: 3451
Create a view model class that wraps employee and supervisor objects as properties. Do this outside of your EF model.
Pass an instance to your view having populated the properties through EF and access the properties to get the values.
Upvotes: 0