[RESOLVED]Two Models in one view

Hi guys,  I am using Asp.net MVC 5.  I want to display two models in one view. Here is my sample code
In ProjectInfo.cs:

 public class ProjectInfo
    {
        [Key]
        //[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public int ProjectCode { get; set; }
        public string ProjectName { get; set; }
        public string ProjectManager { get; set; }
        public int ProjectBudget { get; set; }

        public virtual ICollection<EmployeeInfo> EmployeeInfos { get; set; }

    }

    public class EmployeeInfo
    {
        public int ProjectCode { get; set; }
        [Key]
        public int EmployeeNo { get; set; }
        public string EmployeeName { get; set; }
        public int DepartmentNo { get; set; }
        public string DepartmentName { get; set; }
        public decimal HourlyRate { get; set; }

        public virtual ProjectInfo ProjectInfo { get; set; }
    }

In ViewModel.cs:

 public class ViewModel
    {
        public IEnumerable<ProjectInfo> ProjInfo { get; set; }
        public IEnumerable<EmployeeInfo> EmpInfo { get; set; }
    }

In Controller:

private ProjectDbContext db = new ProjectDbContext();

        // GET: ProjectInfo
        public ActionResult Index()
        {
            ViewModel MyModel = new ViewModel();
            MyModel.ProjInfo = (from x in db.ProjectInfos select x).ToList();
            MyModel.EmpInfo = (from y in db.EmployeeInfos select y).ToList();

            //MyModel.ProjInfo = db.ProjectInfos.ToList();
            //MyModel.EmpInfo = db.EmployeeInfos.ToList();

            return View(MyModel);
            //return View(db.ProjectInfos.ToList());
        }

     ........................
     ........................
     ........................
     ........................

In View/Index.cshtml

@model FirstNormalForm.Models.ViewModel

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ProjectName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ProjectManager)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ProjectBudget)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.EmployeeNo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.EmployeeName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DepartmentNo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DepartmentName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HourlyRate)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectManager)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HourlyRate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProjectCode }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProjectCode }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProjectCode })
        </td>
    </tr>
}

</table>

I run it and got error message. It says

Compilation Error

Description: An error occurred during the compilation of a resource required to service this request.
Please review the following specific error details and modify your source code appropriately. 

Compiler Error Message: CS1061: ‘FirstNormalForm.Models.ViewModel’ does not contain a definition for ‘ProjectName’ and no extension method ‘ProjectName’ accepting a first argument of type ‘FirstNormalForm.Models.ViewModel’ could be found (are you missing
a using directive or an assembly reference?)

Any Idea?

I am waiting for your response.

Thanks

Hi,

You need to change some of "item." to "item.ProjInfo" ie; item.ProjectName" to be "item.ProjInfo.ProjectName", and others
and You need to change some of "model." to "model.ProjInfo" ie; model.ProjectName" to be "model.ProjInfo.ProjectName", and others fields

Also need to change some of "item." to "item.EmpInfo" ie; item.EmployeeName" to be "item.EmpInfo.EmployeeName", and others
and You need to change some of "model." to "model.EmpInfo" ie; model.EmployeeName" to be "model.EmpInfo.EmployeeName", and others fields.

Have fun

If I understood correctly,

As per the view you are trying to display and the two model ProjectInfo and EmployeeInfo are connected.

If you want to display Employee list along with the project each one connected or project list along with the employees connected.

ViewModel should be in two variations’

public class ViewModel// from Project direction
    {
        public ProjectInfo ProjInfo { get; set; }
        public IEnumerable<EmployeeInfo> EmpInfo { get; set; }
    }

or

public class ViewModel//from employee direction
    {
        public ProjectInfo ProjInfo { get; set; }
        public EmployeeInfo EmpInfo { get; set; }
    }

produce list of viewmodels as source to the view

Since you have two collections of properties, you’ll need to specify which ones that you are going to be looping through by adding the appropriate property following your "Model" object within your View :

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ProjectName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ProjectManager)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ProjectBudget)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.EmployeeNo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.EmployeeName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DepartmentNo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DepartmentName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HourlyRate)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model.ProjInfo) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectManager)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HourlyRate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProjectCode }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProjectCode }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProjectCode })
        </td>
    </tr>
}
</table>

Additionally, since it looks like your Employee Info class has an associated property for the Project for each employee : 

public virtual ProjectInfo ProjectInfo { get; set; }

You might be able to simplify your Model by populating this value through an Include and just using a collection of EmployeeInfo objects :

public ActionResult Index()
{
     return View(db.EmployeeInfos.Include("ProjectInfo").ToList());
}

and then just reference the project property when looping through your objects :

<!-- Loop through your Models (EmployeeInfo objects) and reference the ProjectInfo when necessary -->
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectInfo.ProjectName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectInfo.ProjectManager)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectInfo.ProjectBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HourlyRate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProjectCode }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProjectCode }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProjectCode })
        </td>
    </tr>
}

I was thinking that two tables (Join) into one table in View if possible. Here is my table: 

ProjectInfo                         EmployeeInfo

ProjectCode (Key)                EmployeeNo (Key)

ProjectName                       ProjectCode

ProjectManager                   DepartmentNo

ProjectBudget                      DepartmentName

                                          HourlyRate

where ProjectInfo has one and EmployeeInfo has many so it means one to many.

In ProjectInfoController.cs

   public ActionResult Index()
        {
            //ViewModel MyModel = new ViewModel();
            //MyModel.ProjInfo = (from x in db.ProjectInfos select x).ToList();
            //MyModel.EmpInfo = (from y in db.EmployeeInfos select y).ToList();

      
            //var projectInfo = db.Include(c => c.EmployeeInfo);
            var pro = db.EmployeeInfos.Include(c =>c.ProjectInfo);
            return View(pro.ToList());
        }

In Index.cshtml

@model IEnumerable<FirstNormalForm.Models.ProjectInfo> //Two Tables without viewmodel if possible
@*@model FirstNormalForm.Models.ViewModel*@  //<<<Ignore it>>


@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th> Project Code </th>
        <th> Project Name </th>
        <th> Project Manager </th>
        <th> Project Budget </th>
        <th> Employee No </th>
        <th> Employee Name </th>
        <th> Department No </th>
        <th> Department Name </th>
        <th> Hourly Rate </th>
        <th></th>
    </tr>

@foreach (var item in Model.ProjInfo) 
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectCode)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectManager)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProjectBudget)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentNo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DepartmentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HourlyRate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProjectCode }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProjectCode }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProjectCode })
        </td>
    </tr>
}
</table>

Any idea?

adnan_salah84

var pro = db.EmployeeInfos.Include(c =>c.ProjectInfo);

As per the above the statement, you are trying show employees with project info

If my assumption is right, change below statement


adnan_salah84

@Html.DisplayFor(modelItem => item.ProjectCode)

to

@Html.DisplayFor(modelItem => item.ProjectInfo.ProjectCode)

Problem solved. Many thanks, Guys

Leave a Reply