I've been stumped for days.
I have an index page that contains a renderpartial view. A viewmodel is passed to the index page from its controller, then passed from inside the index.cshtml to the renderpartial view as an extension. The renderpartial view is automatically updated every 10 seconds (via jquery function to the controller from the index page) to update its content, which works fine. The index page contains several checkboxfor's that filter out the contents of the renderpartial view. The problem arises when the initial renderpartial view is called when the time period has elapsed, the controller for the renderpartial view does not have the correct model data the controller for the index had prior. Boolean values in the model which were set to true while in the index controller now are false when we get to the renderpartial view. Lets begin...
My Index View:
@model SelfServe_Test2.Models.NGTransCertViewModel
...
<div class="Services_StatusTable" id="refreshme">
@{
Html.RenderPartial("_Data", Model);
}
</div>
...
@Html.CheckBoxFor(m => m.NGTransServicesModel.filter_NJDVSVR24, new { onclick = "test(id)" }) @Html.Label("NJDVSVR24", new { })
...
<script src="~/Scripts/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function () {
setInterval(function () { $('#refreshme').load('/NGTransCertServices/Data'); }, 10000); // every 10 seconds
function test(filter) {
alert(filter);
var serviceChecked = document.getElementById(filter).checked;
$.ajax({
type: "POST",
url: "/NGTransCertServices/ToggleVisibleService",
data: { 'filterOnService': filter, 'serviceChecked': serviceChecked, 'model': @Model },
//success: function (result) {
// if (result === "True")
// alert("yup");
// else
// alert("nope");
//}
});
}
</script>
The PartialView _Data.cshtml:
@model SelfServe_Test2.Models.NGTransCertViewModel
...
<table>
foreach (var item in Model.NGTransServicesList)
{
if (Model.NGTransServicesModel.filter_EBT == true)
{
if (item.Description.Contains("EBT"))
{
}
}
}
</table>
My ViewModel:
namespace SelfServe_Test2.Models
{
public class NGTransCertViewModel
{
public NGTransCertViewModel()
{
NGTransServicesModel = new NGTransCertServicesModel();
NGTransServicesList = new List<NGTransCertServicesList>();
NGTransServices = new NGTransCertServices();
}
public NGTransCertServicesModel NGTransServicesModel { get; set; }
public List<NGTransCertServicesList> NGTransServicesList { get; set; }
public NGTransCertServices NGTransServices { get; set; }
}
}
The Controller:
public class NGTransCertServicesController : Controller
{
NGTransCertViewModel NGT_VM = new NGTransCertViewModel();
NGTransCertServicesModel certServicesModel = new NGTransCertServicesModel();
public ActionResult Index()
{
NGTransCertServices certServices = new NGTransCertServices();
NGT_VM.NGTransServicesModel = certServices.InitServiceTypeCheckBoxes(certServicesModel); // sets all checkboxes to true initially.
return View(NGT_VM);
}
[OutputCache(NoStore = true, Location = System.Web.UI.OutputCacheLocation.Client, Duration = 10)] // in seconds
public ActionResult Data()
{
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
List<NGTransCertServicesList> List_certServices = certDBHandle.GetService();
return PartialView("_Data", NGT_VM);
}
}
Finally, the model where the values are lost:
public class NGTransCertServicesModel
{
...
public bool filter_NJDVSVR24 { get; set; }
...
}
Now then, when the Index.cshtml page is called, i run the InitServiceTypeCheckBoxes method that sets the checkbox values to true, pass the viewmodel to the index page and pass that same model to the renderpartial. All is happy until the 10s timeout is reached and _Data.cshtml is rendered. The checkbox values are now all false.
Let me add a visual element. Below is the model when returning from the controller to the index view with the Boolean set to true as desired. (stepping through)
Below is the model when the index view
Again, in the _Data.cshtml partial view
Now with a breakpoint in the Data action in the controller, that same bool value is now false
The bool does not have the true value even before the first line of code in the Data action.
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
I think the issue is that you're not populating your view model correctly in the Data
method of your controller.
In both methods you're sending the NGT_VM
property to the view, but you only populate some of the data in the Index
method - this data will not be persisted or created by default when you call the Data
method.
Each time a request hits a controller method, that controller is created afresh, and only the constructor and requested method are called. In the case of a request to Data
the controller is created, the NGT_VM
property is set back to the default NGTransCertViewModel
object, with a default NGTransCertServicesModel
object (the boolean property filter_NJDVSVR24
will default to false
). You then create and ignore a variable List_certServices
, but at no point have you updated the NGTransServicesModel
property on the view model to match the values you had from the Index
method.
You should probably assign the NGTransServicesList
variable to the NGT_VM.NGTransServicesList
after you populate it:
[OutputCache(NoStore = true,
Location = System.Web.UI.OutputCacheLocation.Client,
Duration = 10)]
public ActionResult Data()
{
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
List<NGTransCertServicesList> List_certServices = certDBHandle.GetService();
NGT_VM.NGTransServicesList = List_certServices;
return PartialView("_Data", NGT_VM);
}
You could either call same methods to update the NGTransServicesModel
as required in the Data
method, but I'm not sure that's really the behaviour you're after?