问题
Thanks in advance. Please excuse me for my grammer. I tried my best to explain my issue In my quest of solving below question I started to develop a POC first.
C# MVC No submit pass object between views
I am having an issue using TempData object and pass my model between my parent popup and child popup. My problem is I am doing TempData["StudentViewModel"] 2 times. First time insert and First time read are good but Second time read even though I make sure that I insert second time before read is not working.
I will try my best to explain it clearly.
I have a ASP.NET page called Class.cshtml. It will have a grid of all class. The user will select a ClassName column and it opens up Students.cshtml as a new popup window which has a grid with StudentName and Address columns. The user will select StudentName and it opens another popup window called StudentDetails.cshtml.
We have a ClassController.cs which is used by all popups and have C# methods. ClassController.js has all javscript code.
public ActionResult GetStudentsDetails()
{
// this will create students for each class.
//Inside student for each class it will also create Student Details.
// First Insert
TempData["StudentViewModel"] = studentViewModel;
return View("Students", studentViewModel);
}
Students.cshtml is an existing popup window like below
<div>
//this is in for loop
string anchorElementId = string.Format("AnchorElementId_{0}", i);
string selectedIndex = i.ToString();
string name = Model.Students[i].Name;
<input class="ButtonLikeHyperLink"
id="myBtnId"
onclick="ShowStudentDetails(@selectedIndex, '@name', '@anchorElementId')"
value="@Model.Students[i].Name"
type="button"/>
//for loop ends here
//First read
<span id="lblHDNStudentViewModel">
@Newtonsoft.Json.JsonConvert.SerializeObject(TempData["StudentViewModel"] as StudentViewModel)
</span>
</div>
Once user selects any StudentName in Students.cshtml popup the below js method is called which opens a Child window popup having particular student details.
ClassController.js
function ShowStudentDetails(selectedIndex, name, anchorElementId)
{
var inputParam = {};
var hiddenField = document.getElementById("lblHDNStudentViewModel");
if (hiddenField != null)
{
inputParam.StudentVM = JSON.parse(hiddenField.innerText);
inputParam.selectedIndex = selectedIndex;
inputParam.name = name;
inputParam.anchorElementId = anchorElementId;
// __callback is our custom method to call controller action method
var retVal = __callback("OnNameSelected", inputParam);
var postedData = JSON.parse(retVal.return_value);
if (postedData.Success == true)
{
// i need to do like below since Model to my popup is dynamic
multipleMatchPopup = window.open('', '', properties);
multipleMatchPopup.document.write(postedData.PartialViewHtml);
}
}
}
ClassController.cs
public JsonResult OnNameSelected(StudentViewModel StudentVM, int selectedIndex, string name, string anchorElementId)
{
// this will create student name details viewmodel for selected name and modify StudentViewModel object.
// for example
StudentDetailsViewModel vm = StudentVM[selectedIndex].DetailsVM;
//since user made selection update few properties in vm
StudentVM[selectedIndex].DetailsVM = vm;
//Second insert
// make sure to set tempdata before RenderPartialViewToString
TempData["StudentViewModel"] = StudentVM;
string sHtml = this.RenderPartialViewToString("~/Views/_PartialStudentDetailsPopup.cshtml", vm);
return Json(new
{
Success = true,
data = StudentVM,
PartialViewHtml = sHtml,
JsonRequestBehavior.AllowGet
});
}
In StudentDetails.cshtml popup I have like this
<div>
.....
<input class="ButtonLikeHyperLink"
id="@buttonId"
onclick="OnUserSelectStudentDetails()"
value="[Select]"
type="button" />
//Second read
//in fiddler innertext is show as null
<span id="lblHDNStudentDetailsViewModel">
@Newtonsoft.Json.JsonConvert.SerializeObject(TempData["StudentViewModel"] as StudentViewModel)
</span>
</div>
ClassController.js
function OnUserSelectStudentDetails()
{
var inputParam = {};
var hiddenField = document.getElementById("lblHDNStudentDetailsViewModel");
if (hiddenField != null)
{
//hiddenField.innerText is null
inputParam.StudentVM = JSON.parse(hiddenField.innerText);
var retVal = __FAFdoCallback("OnUserSelectLenderMatchingFee", inputParam);
...
}
}
ClassController.cs
public JsonResult OnUserSelectLenderMatchingFee(StudentViewModel StudentVM)
{
//StudentVM is null here
}
UPDATE
SOLUTION
I feel real stupid on this issue. As the great detective, Hercule Poirot said, "The great gray cells are not working", mine also did not work in this case. Sometimes we think so far away from the box that we oversee the basics. I was thinking that this thing cannot be done in so simple so I was thinking about TempData and so on and forgot the fundamental point that my parent popup already have a hidden field and I can read from it and write to it it in my javascript methods of parent and child popups windows and pass it to controller action methods and get back updated and consistent model back.
Taking this basic solution this is what I did
Students.cshtml
<span id="lblHDNStudentViewModel">
@Newtonsoft.Json.JsonConvert.SerializeObject(Model)
</span>
Read this in parent window javascript method like below in ClassController.js
function ShowStudentDetails(selectedIndex, name, anchorElementId)
{
var inputParam = {};
//read
var hiddenField = document.getElementById("lblHDNStudentViewModel");
}
Read this from child window javascript method like below in ClassController.js
function OnUserSelectStudentDetails()
{
var inputParam = {};
// read in child window and access parent window element
var hiddenField = window.opener.document.getElementById("lblHDNStudentViewModel");
}
Write back to parent window element from parent window javascript method like below
document.getElementById("lblHdnCDLenderViewModel").innerText = JSON.stringify(postedData.data);
Write back to parent window element from child window javascript method like below
window.opener.document.getElementById("lblHdnCDLenderViewModel").innerText = JSON.stringify(postedData.data);
来源:https://stackoverflow.com/questions/36729567/mvc-pass-model-between-parent-and-child-window