In my main view, I am iterating through the List using a for loop with
i as an index. I want to call a partial view from within this main
page to avoid repeat code across the system but this partial view
needs to be aware of the index number as well as the job id and site
id.
I cannot just pass in in Model.ListAModel[i] as this will not be aware
of job or site id, and likewise with the other way round.
From your description, I assume you want to filter data based on the Job id and site id, then display the AModel via the partial view.
To pass parameters from main page to the partial view, you can use the view-data
attribute. Please refer the following sample:
Model:
public class JobViewModel
{
public int JobID { get; set; }
public int SiteID { get; set; }
public List<AModel> ListAModel { get; set; }
}
public class AModel
{
public int ID { get; set; }
public string Name { get; set; }
public int JobID { get; set; }
public int SiteID { get; set; }
}
Controller:
public IActionResult Index4()
{
var initialdata = new List<JobViewModel>()
{
new JobViewModel(){
JobID = 1001,
SiteID = 102,
ListAModel = new List<AModel>()
{
new AModel(){ ID=1, Name="Joe", JobID=1001, SiteID=101},
new AModel(){ ID=2, Name="Merry", JobID=1001, SiteID=102},
new AModel(){ ID=3, Name="Henry", JobID=1001, SiteID=103},
new AModel(){ ID=4, Name="Cody", JobID=1001, SiteID=101},
new AModel(){ ID=5, Name="Simon", JobID=1001, SiteID=102},
new AModel(){ ID=6, Name="Leena", JobID=1001, SiteID=103},
new AModel(){ ID=7, Name="Ode", JobID=1001, SiteID=101},
new AModel(){ ID=8, Name="Nicky", JobID=1001, SiteID=102},
}
}
};
return View(initialdata.FirstOrDefault());
}
Main page: using ViewData and view-data
attribute to pass parameters.
@model MVCWebApplication.Models.JobViewModel
@{
ViewData["JobID"] = Model.JobID.ToString();
ViewData["SiteID"] = Model.SiteID.ToString();
}
<div>
<h4>JobViewModel</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.JobID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.JobID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.SiteID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.SiteID)
</dd>
</dl>
<div class="form-group">
<partial name="_AModelPV.cshtml" model="@Model.ListAModel" view-data="ViewData"/>
</div>
</div>
Partial View (_AModelPV.cshtml): In the partial view, you could also check whether the ViewData exists and contains the value.
@model IEnumerable<MVCWebApplication.Models.AModel>
@{
var jobid = Convert.ToInt32(ViewData["JobID"]);
var siteid = Convert.ToInt32(ViewData["SiteID"]);
}
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.ID)
</th>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.JobID)
</th>
<th>
@Html.DisplayNameFor(model => model.SiteID)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Where(c=>c.JobID == jobid && c.SiteID == siteid).ToList()) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.JobID)
</td>
<td>
@Html.DisplayFor(modelItem => item.SiteID)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</tbody>
</table>
The result like this:

Besides, you could also consider filtering the data before sending data to the main page. For example, in the above action method, filter the data based on the JobID and SiteID, then return the result to the main page. In this scenario, the ListAmodel contains the filtered data, there is no need to do the filter action in the partial view.
var result = initialdata.Select(c =>
new JobViewModel {
JobID = c.JobID, SiteID = c.SiteID,
ListAModel = c.ListAModel.Where(d => d.JobID == c.JobID && d.SiteID == c.SiteID).ToList() })
.FirstOrDefault();
return View(result);