Save a dynamic data set using AJAX in MVC - c#

I have a razor view in which I generate the controls on the page generically by using a foreach loop on a list of data from a database. I am using DevExpress for my controls but I don't think that matters too much for solving this problem.
var docTypes = MyProject.GetDocumentTypes();
foreach(var docType in docTypes)
{
//Add controls (Example Control Below)
groupItem.Items.Add(i =>
{
i.Name = "checkDoc" + docType.Id;
i.NestedExtensionType = FormLayoutNestedExtensionItemType.CheckBox;
});
}
Usually when I write an AJAX call to save this data, I would write something like this. Note that this is being called when clicking a save button specifically:
function updateDocs() {
$.ajax({
url: '#Url.Action("SaveDocs", "Home")',
data: {
key: '#(Model.Id)',
docChecked: checkDoc1.GetValue(),
}, success: function(data){
},
error: function(data){
}
});
}
Then with the method:
public JsonResult SaveDocs(int key, bool docChecked)
{
//Save the data here
return Json(new { isSuccess = true },
JsonRequestBehavior.AllowGet
);
}
However, if I am generating the controls at runtime, I cannot know what exactly there is to pull for my parameters for the data section.
I was thinking that if I could somehow get this data into a Dictionary or something then I could pass it generically to a function with a parameter that accepts that Dictionary. If I can pass just some key data points to my Controller I can figure out how to save it from there. I would just need the value that the control holds and the control name itself passed in the simplest solution.
Thanks in advance for any assistance with this problem.

in your controller you can use this (this allows you to send any number of params of any type and parse them in the Action)
[HttpPost]
public JsonResult PostData(dynamic postData)
{
Dictionary<string,string> data = JsonConvert.DeserializeObject<Dictionary<string, string>>(((Newtonsoft.Json.Linq.JObject)postData)["data"].ToString());
...........
}
Or just send a dictionary
[HttpPost]
public JsonResult PostData(Dictionary<string,string> postData)
{
.......
}
The js call (for dynamic data type)
$http({
method: "POST",
url: Helper.ApiUrl() + '...',
data: { customer, applicant, accountNumber,... },
})

Related

Jquery .post method is sending a null value. How to pass actual value to controller?

I have a controller that applies to an edit view in asp.net MVC. I have an actionlink that sends the row Id to the controller which then brings back the correct row to see in the associated view.
I then have a partial view below that. That also requires a parameter in order to bring associated data from another table.
I have a Jquery .post call that runs after the page is loaded. I can alert out and show the exact value I want to send to the controller.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").serialize();
alert(Uc);
$.post(url, {Id: Uc}, function (data) {
alert("what is Uc now? " + uc); //just for testing
});
})
I have also used it this way.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").val();
alert(Uc);
$.post(url, Uc, function (data) {
});
})
the alerts come up and show the value I want. However, when the .post call runs, it sends a null value. Here is my controller.
public ActionResult MmsAndNotes(string Id)
{
//Declare LogisticsVM for individual policy info
LogisticsMMS_NotesVM model;
if(uc == null)
{
return Content("uc is empty.");
}
int val = Convert.ToInt32(uc);
using (Db db = new Db())
{
LogisticsMMS_NotesDTO dto = db.LogisticsMMS.Find(val);
//confirm policy exists
if (dto == null)
{
return Content("This policy cannot be found." + val);
}
model = new LogisticsMMS_NotesVM(dto);
}
return PartialView(model);
}
It always returns as uc is empty. I repeat, when the alerts come up. I get the correct value to send to the controller. But once it sends, something happens and it converts to null. HELPPPPP.. please .. I'm losing my mind over this one.
I don't know why, but changing my $.post() call to an $.ajax({}) call solved the issue. As you can see above, I had the $.post call. Using this instead,
$.ajax({
type: "POST",
url: "/Home/MmsAndNotes",
dataType: 'text',
data: { Id: Uc }
});
Solved it. I thought Jquery's shortened calls worked the same way. They certainly might, but doing it this way was the only way it worked for me.
P.S. Thanks Tyler (above) for your comments.
this solution should be work :
$(document).ready(function () {
$.ajax({
url: '/Home/MmsAndNotes',
type: 'GET',
dataType: "html",
data: { uc : $("#Id").val() },
success: function (result) {
code here
}
});
})
You need to verify if $("#Id").val() is not empty

mvc controller pameter getting null value in ajax call

I am making ajax call like this
deleteAge(item: any): string {
$.ajax({
method: "POST",
url: 'DeleteAge',
data: item.Id(),
success: (response) => {
toastr.success("ready soon");
},
error: (event) => {
toastr.error("Error occured ");
}
}).always(() => {
});
return "";
}
Here is my method in controller which is currently nothing almost implemented
[HttpPost]
public ActionResult DeleteAge(string id)
{
throw new Exception();
}
when i run the code then in my controller i dont get any id.. its null. when i debug my javascript code then this code item.Id() is not blank. Even if i pass hardcoded value to data in ajax call still controller gets null. What is wrong?
Rather than using:
data: item.Id(),
I'd suggest using:
data: { id: item.Id()},
This way the id value is associated with the id name - allowing model binding to work correctly.
Pass parameters like json format in ajax
replace data: item.Id() with data: {id: 1}

Pass custom collection object from Controller to View with JQuery

I have a custom object that derives from IEnumerable. This collection is pretty complex because it contains object which themselves contain collections of other objects. Simply put, it is a multiple dimension array.
I have a drop down list on my view that gets populated with a server call of items, and when a certain item is selected, it calls the server to get the associated collection object for that item.
I inherited this code and initially when the first drop down was selected a second drop down is enabled and the user selects a single item. The second drop down is populated with the items in the collection (the collection itself is parsed through to simply get the name and id number of the item).
Now, instead of a second drop down, I want to actually return the collection to the view and have my view loop through and display the contents of the collection and all that good stuff.
My question is how can I transfer this collection object from my controller to my view.
Here is the code in the controller which will grab the collection based on the value of the drop down.
public ActionResult GetWorkbooks(string term, int projectId = -1)
{
if (this.SelectedProject != projectId)
{
try
{
WorkBookDataManager dataManager = new WorkBookDataManager();
this.WorkbookColl = dataManager.GetWorkBooksById(null, projectId, null);
this.SelectedProject = projectId;
}
catch (Exception exc)
{
log.Error("Could not load projects", exc);
}
}
return this.View("_Workbook", this.WorkbookColl);
}
This code will return a partial view with the collection as a model.
But how can I use that with the existing JQuery code when the drop down has a value selected?
Here is the drop down code:
// Populate the first drop down
var loadProjects = function (request, response) {
$.ajax({
url: $("#projects").attr("data-vs-autocomplete"),
dataType: "json",
type: "POST",
data: { term: request.term }
})
.always(function (data, status) { getResponse(response, data, status); });
};
// If the first drop down has an item selected enable the second drop down
var projectSelected = function (event, ui) {
var projectId = $("#projects").data(VS_AUTOCOMPLETE_VALUE);
var enable = projectId ? false : true;
/*$("#workbooks").prop('disabled', enable);
$("#workbooks").val("");
$("#workbooks").data(VS_AUTOCOMPLETE_VALUE, "");
$("#workbooks").data(VS_AUTOCOMPLETE_TEXT, "");*/
$("#workbook").html("<p>No workbook selected</p>");
};
// Function to get the second drop down items
// This is the function I think needs to be modified to accept the collection object from the server
var loadWorkbooks = function (request, response) {
$.ajax({
url: $("#workbooks").attr("data-vs-autocomplete"),
dataType: "json",
type: "POST",
data:
{
term: request.term,
projectId: $("#projects").data(VS_AUTOCOMPLETE_VALUE)
}
})
.always(function (data, status) { getResponse(response, data, status); });
};
// Second drop down -> This needs to be removed
var workbookSelected = function (event, ui) {
$("#workbooks").blur(); // this prevents the workbook dropdown from focusing.
LoadWorkbook();
};
// These functions populated the drop downs with items
Autocomplete($("#projects"),
{ autoFocus: true,
minLength: 0,
source: loadProjects,
select: projectSelected
});
Autocomplete($("#workbooks"),
{ autoFocus: true,
minLength: 0,
source: loadWorkbooks,
select: workbookSelected
});
I want to make this simple so if there is a better way to do all of this and restructure the controller and/or jquery, I am all ears (eyes).
Let me know if more information is needed or if anything is unclear.
Thanks
"Best practice" here is single responsibility principle, i.e. separate actions for getting the data that should be displayed in dropdown and the same data that is rendered as partial view. Basically all you need is a method to retrieve the model, and one action that serializes the model and return in form of JSON, another - returns partial view. Controller:
private Workbook GetWorkbooksByProject(int projectId)
{
WorkBookDataManager dataManager = new WorkBookDataManager();
var workbookColl = dataManager.GetWorkBooksById(null, projectId, null);
return workbookColl;
}
public JsonResult GetWorkbooks(int projectId)
{
var model = GetWorkbooksByProject(projectId);
return Json(model, JsonRequestBehavior.AllowGet);
}
public ActionResult WorkbooksList(string term, int projectId = -1)
{
if (this.SelectedProject != projectId)
{
try
{
this.WorkbookColl = GetWorkbooksByProject(projectId);
this.SelectedProject = projectId;
}
catch (Exception exc)
{
log.Error("Could not load projects", exc);
}
}
return this.View("_Workbook", this.WorkbookColl);
}
From client side you must change the url to post data to GetWorkbooks action method and you are good to go.
Advantages of this approach is that populating the dropdown will not execute any other logic than retrieving workbooks list and at client side you can now easily leverage any binding framework (e.g. KnockoutJS) or plain javascript to render your model, even if your html markup will be changed in future from simple dropdown to more complex ui.

DataTable to JSON to Controller to jqGrid

I have 3 forms, Associate.cs, HomeController.cs, Index.cshtml.
I load a DataTable from Associate.cs and use this code to get it into JSON format.
public string GetAssociateFromDB()
//code omitted
var json = JsonConvert.SerializeObject(dt, Formatting.Indented);
jsonData = json;
}
}
return jsonData; //return is good
I call this from HomeController.cs.
public JsonResult GetJsonData()
{
Associate associate = new Associate();
string jsonData = associate.GetAssociateFromDB();
System.Diagnostics.Debug.WriteLine(jsonData); //for testing purposes
return Json(jsonData, JsonRequestBehavior.AllowGet); //need to pass to `Index.cshtml`
}
However, this code doesn't get hit unless I put the method in this block:
[HttpGet]
public ActionResult Index()
{
GetJsonData(); //if not called here, it never gets hit.
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
Then, I try to pass it to Index.cshtml, via $.getJSON method, but it never reaches it.
jQuery(document).ready(function () {
var mydata;
$.getJSON('#Url.Action("HomeController", "GetJsonData")', function(data) {
datatype: 'json'
mydata = data;
console.log(data); //unsure if this works or not.
});
I am then trying to supply that data for a jqGrid (this is just under the above code):
$("#grid").jqGrid({
data: mydata,
datatype: "json",
width: '100%',
colNames: ["Seq ID", "Fund ID", "Name", "Fund", "Bonus", "Allocation", "Blank", "Begin", "End"],
colModel: [{
name: 'seqid',
index: 'seqid',
editable: true,
},....//Code omitted
I can't seem to get the data from the Controller to Index.cshtml.
I have read on a blog that there is a problem with cache in IE 8, which is what I am testing in, but I'm pretty sure that's not my initial problem.
I've read the jQGrid documentation and searched many times, but the only example is for this kind of thing is for PHP or in a different context. I tried putting [HttpGet] above the GetJsonData method, and that did not work either.
It's also important to note I haven't written much(any) jQuery before.
Try this below code.
Url.Action('actionname','controllername')
javascript:
$(document).ready(function () {
var mydata;
$.getJSON('#Url.Action("GetJsonData", "Home")', function(data) {
datatype: 'json'
mydata = data;
gridFn(data);
});
function gridFn(data)
{
//here grid code
}

display json data from controller inside view

Inside my controller there is JsonResult action which returns me a list of House object.
I want onclick using ajax to retrieve these data and to display json data inside my view.
Inside firebug I'm able to see proper Response and Json result but I dont know how to display inside my view.
function GetTabData(xdata) {
$.ajax({
url: ('/Home/GetTabData'),
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ id: xdata }),
success: function (result) {
// tried with these but it doesnt work
// result = jQuery.parseJSON(result);
// alert(result.Title);
},
error: function () { alert("error"); }
});
}
public JsonResult GetTabData()
{
...
var temp = getMyData...
return Json(temp, JsonRequestBehavior.AllowGet);
}
// View page
<div id="showContent">
// Json data should appear here
</div>
Inside firebug JSON tab when success:function(result) is empty
I have following data:
Id 149
PropertyType "Apartment"
StreetNumber "202B"
CityName "Sidney"
Title "My test data"
success: function (json) {
var data = null;
$.each(json.items,function(item,i){
data = '<div>'+item.Id+ ' ' + item.CityName +'</div>';
$("#showContent").append(data);
});
}
First of all, you can specify the dataType attribute in your ajax call to 'json' and then don't have to decode the json response again -
dataType: 'json'
Then, you don't need to use parseJSON. Simply use result.Title etc.
success: function (result) {
alert(result.Title);
var showContent = $('#showContent');
showContent.html(result.Id+','+result.Title);
},
EDIT: As Mukesh said, you can have the ajax function return json without using any extra decoding.
The ajax call result is already an object. You can do whatever you want with it it inside the success function.
For example you could create a table of the information dynamically inside the function, or send the data to another function by calling the function inside that success function. Once you leave the success function, the data is not usable anymore.
Access the data object like any object (data.someProperty).

Categories