Currently i have a scaffolded create view that submits to a controller with a regular post. I then have a partial view that submits to a seperate controller via an AJAX post. All of this works very nicely. But now i need to grab the ID from the submit of
the Create view and use that ID inside my AJAX post. Whats the best way to go about this? I can return the ID fine. I had a look at returning a javascript result but couldnt get that to work. Plus i would need to preserve the page somehow.
Is there a way to change the create View to allow me to pass a second model to the Controller on submit? Or do i need to code that all using AJAX?
If i was to post all the values to a controller using AJAX, how would i go about using the DataAnnotations (particularly the clientside stuff)
That would be ideal, however whenever i return the ID i cant figure out how to maintain the user input in the partial view. I need to grab a hidden ID from the text box and the value of the textbox and then submit it again.
scaffolding write down just some code to "start with"...Define a new ViewModel class and put the two models you would like to insertin the view as two properties of the ViewModel....then modify the Controller code accordingly.
Thanks, i had definitely thought about going that route. However my partial view contains dynamic data and a varying length of textbox fields depending on the selections. I havent been able to figure out a way to get that data without using jquery.
So far what i have done is use jquery to post the whole form to a controller with my new ViewModel which works fine. I can see all the right data when it hits the controller.
But now my concern is what do i wire this up to? If i wire it up to a submit button inside a form then i need to add a controller and action (which it shouldnt hit). it seems that the action will execute as well as the ajax request which is exactly what i dont want. If i wire it up to a regular button with just an onClick then i lose my client side validation. Is there a way to call the client side validation manually? Here is the ajax post,
function saveFormData() {
var equipDatas = new Array();
var customPropertyList = new Array();
equipDatas = {
equipmentType_ID: 1,
SerialNumber: 1,
Manufacturer_ID: 1,
BusinessUnit_ID: 1,
CurrentStatus_ID: 1
};
for (var i = 0; i < $("input:text[name^=txt]").length; i++) {
customPropertyList[i] = {
equipment_ID: 1,
customPropertyName_ID: $("#Hidden" + i).val(),
Value: $("#txt" + i).val()
};
}
var url = '@Url.Action("DummyCreate")';
$.ajax({
type: "POST",
url: url,
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ equip: equipDatas, custData: customPropertyList }),
datatype: "JSON"
});
}
Ok i finally got this to work the way i want it to. Thanks to Francesco for making me go down the ViewModel route. Ill post the entire code (there is a lot)
Here is the partial view that is rendered on via ajax on a selectedIndexChanged event. The important parts to note for me were: No form tags (everything seemed to work when i removed them, they were originally there from some messing around i had been doing), and setting the name of the textBox to be custData[+i+].Value
@model ZITS_BO.ViewModels.vmEquipment
<table>
@for (var i = 0; i < Model.custData.Count; i++)
{
<tr><td>
@Html.HiddenFor(model => model.custData[i].customPropertyName_ID) @Html.DisplayFor(model => model.custData[i].Value)</td>
<td>
@Html.TextBox("custData[" + i + "].Value")
</td>
</tr>
}
</table>
Here is the controller
[HttpPost]
public ActionResult Create(ZITS_BO.ViewModels.vmEquipment vm)
{
if (ModelState.IsValid)
{
//Save the new equipment to the equipment table
int newID = be.addEquipment(vm.equipData);
if (vm.custData.Count != 0)
{
foreach (ZITS_BO.boCustomProperties.ajaxPostData apd in vm.custData)
{
//Add the reponses to the customnameValues table with the new ID.
}
}
return RedirectToAction("Index");
}
return View(vm);
}
The viewmodel is 2 partial classes, one being a list (custData). Hopefully this can help someone out
alm1
Member
133 Points
60 Posts
Posting data with returned ID from controller
Feb 26, 2012 11:57 PM|LINK
Hi All
Currently i have a scaffolded create view that submits to a controller with a regular post. I then have a partial view that submits to a seperate controller via an AJAX post. All of this works very nicely. But now i need to grab the ID from the submit of the Create view and use that ID inside my AJAX post. Whats the best way to go about this? I can return the ID fine. I had a look at returning a javascript result but couldnt get that to work. Plus i would need to preserve the page somehow.
Is there a way to change the create View to allow me to pass a second model to the Controller on submit? Or do i need to code that all using AJAX?
If i was to post all the values to a controller using AJAX, how would i go about using the DataAnnotations (particularly the clientside stuff)
Thanks
Andy
alm1
Member
133 Points
60 Posts
Re: Posting data with returned ID from controller
Feb 29, 2012 06:17 PM|LINK
anyone?
jsucupira
Member
566 Points
144 Posts
Re: Posting data with returned ID from controller
Feb 29, 2012 06:21 PM|LINK
Couldn't you save that ID in a ViewBag or ViewData than use that on your ajax post?
alm1
Member
133 Points
60 Posts
Re: Posting data with returned ID from controller
Feb 29, 2012 07:41 PM|LINK
That would be ideal, however whenever i return the ID i cant figure out how to maintain the user input in the partial view. I need to grab a hidden ID from the text box and the value of the textbox and then submit it again.
francesco ab...
All-Star
20912 Points
3279 Posts
Re: Posting data with returned ID from controller
Feb 29, 2012 08:15 PM|LINK
scaffolding write down just some code to "start with"...Define a new ViewModel class and put the two models you would like to insertin the view as two properties of the ViewModel....then modify the Controller code accordingly.
Mvc Controls Toolkit | Data Moving Plug-in Videos
alm1
Member
133 Points
60 Posts
Re: Posting data with returned ID from controller
Mar 01, 2012 01:04 AM|LINK
Thanks, i had definitely thought about going that route. However my partial view contains dynamic data and a varying length of textbox fields depending on the selections. I havent been able to figure out a way to get that data without using jquery.
So far what i have done is use jquery to post the whole form to a controller with my new ViewModel which works fine. I can see all the right data when it hits the controller.
public ViewResult dummyCreate(ZITS_DAL.Equipment equip, List< ZITS_BO.boCustomProperties.ajaxPostData> custData) { return View(equip); }But now my concern is what do i wire this up to? If i wire it up to a submit button inside a form then i need to add a controller and action (which it shouldnt hit). it seems that the action will execute as well as the ajax request which is exactly what i dont want. If i wire it up to a regular button with just an onClick then i lose my client side validation. Is there a way to call the client side validation manually? Here is the ajax post,
function saveFormData() { var equipDatas = new Array(); var customPropertyList = new Array(); equipDatas = { equipmentType_ID: 1, SerialNumber: 1, Manufacturer_ID: 1, BusinessUnit_ID: 1, CurrentStatus_ID: 1 }; for (var i = 0; i < $("input:text[name^=txt]").length; i++) { customPropertyList[i] = { equipment_ID: 1, customPropertyName_ID: $("#Hidden" + i).val(), Value: $("#txt" + i).val() }; } var url = '@Url.Action("DummyCreate")'; $.ajax({ type: "POST", url: url, contentType: "application/json; charset=utf-8", data: JSON.stringify({ equip: equipDatas, custData: customPropertyList }), datatype: "JSON" }); }Thanks Andy
alm1
Member
133 Points
60 Posts
Re: Posting data with returned ID from controller
Mar 01, 2012 09:41 PM|LINK
Ok i finally got this to work the way i want it to. Thanks to Francesco for making me go down the ViewModel route. Ill post the entire code (there is a lot)
@model ZITS_BO.ViewModels.vmEquipment @{ ViewBag.Title = "Create"; ZITS_BO.boEquipment be =new ZITS_BO.boEquipment(); ZITS_BO.boCustomProperties bcp = new ZITS_BO.boCustomProperties(); } <div class="equipmentHeader">New Equipment</div><br /> <script type="text/javascript" src="../../scripts/jquery.fancybox.pack.js"></script> <script type="text/javascript"> $(document).ready(function () { $(".fancyboxEquip").fancybox({ 'type': 'iframe', 'height': 400, 'width': 800, 'maxWidth': 800, 'maxHeight': 400, 'beforeShow': function () { $('iframe').contents().html('Hello'); }, 'beforeClose': function () { var sender = this.element.attributes[0].nodeValue; sender = sender.substring((sender.indexOf("/") + 1), sender.lastIndexOf("/")); $.post("/Equipment/reloadEquipmentType", { ssender: sender }, function (data) { $('div#' + sender + '.data').html(data + '<a class="fancyboxEquip" href="../'+ sender + '/Create"><img title="Click here to add Equipment Type" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a>'); }) } }); }); $(document).ready(function () { $(".fancybox").fancybox({ 'type': 'iframe', 'height': 400, 'width': 800, 'maxWidth': 800, 'maxHeight': 400 }); }); $("a.ancybox").each(function () { var tthis = this; $(this).fancybox({ type: 'iframe', 'height': 800, 'width': 800 }); }); function checkSerialExists() { $.post("/Equipment/checkSerialExists", { serialNumber: $("#serialNumber").val() }, function (data) { var myObject = eval('(' + data + ')'); var newid = myObject; if (newid == 0) { $("#serialNumberDiv").html(""); } else { $("#serialNumberDiv").html("<font color='green'>This Serial Number already exists. Click <a class='ancybox' href='../equipment/serialSearchIndex/" + $("#serialNumber").val() + "' target='_blank'>here </a> to view the entry </font>"); } }); } function showCustomProperties() { $.post("../CustomPropertyNames/loadProperties", { equipmentType_id: $("#lstEquipmentType").val() }, function (data) { $("#customProp").html(data); }); } $(document).ready(function () { if ($("#lstEquipmentType").val() != "") { showCustomProperties() } }); </script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <table> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.EquipmentType_ID, "Type of Equipment") </td> <td class="editor-field"> <div id="EquipmentType" class="data"> @Html.DropDownListFor(model => model.equipData.EquipmentType_ID, null, "Please select a value", new { @class = "dropDownStyle", id = "lstEquipmentType", @onchange = "showCustomProperties()" }) <a class="fancyboxEquip" href="../EquipmentType/Create"><img title="Click here to add Equipment Type" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a> @Html.ValidationMessageFor(model => model.equipData.EquipmentType_ID, null, new { @class = "ui-state-error" }) </div> </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.SerialNumber, "Serial Number", null) </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.SerialNumber, null, new { @id = "serialNumber", onblur = "checkSerialExists()" }) <div style="display:inline;" id="serialNumberDiv"></div> @Html.ValidationMessageFor(model => model.equipData.SerialNumber) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.Manufacturer_ID, "Manufacturer") </td> <td class="editor-field"> <div id="Manufacturer" class="data"> @Html.DropDownListFor(model => model.equipData.Manufacturer_ID, null, "Please select a value", new { @class = "dropDownStyle" }) <a class="fancyboxEquip" href="../Manufacturer/Create"><img title="Click here to add Manufacturer" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a></div> @Html.ValidationMessageFor(model => model.equipData.Manufacturer_ID, null, new { @class = "ui-state-error" }) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.Model) </td> <td class="editor-field"> @Html.EditorFor(model => model.equipData.Model) @Html.ValidationMessageFor(model => model.equipData.Model) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.BusinessUnit_ID, "Business Unit") </td> <td class="editor-field"> <div id="BusinessUnit" class="data"> @Html.DropDownListFor(model => model.equipData.BusinessUnit_ID, null, "Please select a value", new { @class = "dropDownStyle" }) <a class="fancyboxEquip" href="../BusinessUnit/Create"><img title="Click here to add Business unit" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a> </div> @Html.ValidationMessageFor(model => model.equipData.BusinessUnit_ID, null, new { @class = "ui-state-error" }) </td> </tr><tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.Location_ID, "Item Location") </td> <td class="editor-field"> <div id="Location" class="data"> @Html.DropDownListFor(model => model.equipData.Location_ID, null, "Please select a value", new { @class = "dropDownStyle" }) <a class="fancyboxEquip" href="../Location/Create"><img title="Click here to add Location" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a> </div> @Html.ValidationMessageFor(model => model.equipData.Location_ID, null, new { @class = "ui-state-error" }) </td> </tr><tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.Warranty, "Warranty Length") </td> <td class="editor-field"> @Html.EditorFor(model => model.equipData.Warranty) @Html.ValidationMessageFor(model => model.equipData.Warranty) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.Value, "Value of Equipment") </td> <td class="editor-field"> @Html.EditorFor(model => model.equipData.Value) @Html.ValidationMessageFor(model => model.equipData.Value) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.OrderDate, "Date Ordered") </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.OrderDate, null, new { @readonly = "readonly" })</td> <td class="ui-datepicker"> @Html.Partial("_DatePicker", null) @Html.ValidationMessageFor(model => model.equipData.OrderDate) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.StartupDate, "Date equipment first used") </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.StartupDate, null, new { @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.equipData.StartupDate) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.LastInspectionDate, "Last Inspection Date") </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.LastInspectionDate, null, new { @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.equipData.LastInspectionDate) </td> </tr><tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.NextInspectionDate, "Next Inspection Date") </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.NextInspectionDate, null, new { @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.equipData.NextInspectionDate) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.LastPhysicalInventoryDate, "Equipment Last Seen") </td> <td class="editor-field"> @Html.TextBoxFor(model => model.equipData.LastPhysicalInventoryDate, null, new { @readonly = "readonly" }) @Html.ValidationMessageFor(model => model.equipData.LastPhysicalInventoryDate) </td> </tr> <tr> <td class="editor-label"> @Html.LabelFor(model => model.equipData.CurrentStatus_ID, "Status of Item") </td> <td class="editor-field"> <div id="Status" class="data"> @Html.DropDownListFor(model => model.equipData.CurrentStatus_ID, null, "Please select a value", new { @class = "dropDownStyle" }) <a class="fancyboxEquip" href="../Status/Create"><img title="Click here to add Status" class="equipmentAddImage" src="../../Content/Images/add-icon.png" alt="Add" /></a> </div> @Html.ValidationMessageFor(model => model.equipData.CurrentStatus_ID, null, new { @class = "ui-state-error" }) </td> </tr> <tr><td></td></tr> </table> <div id="customProp"> </div> <input type="button" /> <input type="submit" value="Create" id="btn" /> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>Here is the partial view that is rendered on via ajax on a selectedIndexChanged event. The important parts to note for me were: No form tags (everything seemed to work when i removed them, they were originally there from some messing around i had been doing), and setting the name of the textBox to be custData[+i+].Value
@model ZITS_BO.ViewModels.vmEquipment <table> @for (var i = 0; i < Model.custData.Count; i++) { <tr><td> @Html.HiddenFor(model => model.custData[i].customPropertyName_ID) @Html.DisplayFor(model => model.custData[i].Value)</td> <td> @Html.TextBox("custData[" + i + "].Value") </td> </tr> } </table>Here is the controller
[HttpPost] public ActionResult Create(ZITS_BO.ViewModels.vmEquipment vm) { if (ModelState.IsValid) { //Save the new equipment to the equipment table int newID = be.addEquipment(vm.equipData); if (vm.custData.Count != 0) { foreach (ZITS_BO.boCustomProperties.ajaxPostData apd in vm.custData) { //Add the reponses to the customnameValues table with the new ID. } } return RedirectToAction("Index"); } return View(vm); }The viewmodel is 2 partial classes, one being a list (custData). Hopefully this can help someone out