It seems things have become more complex going from ASP.NET MVC to .NET Core because I can no longer easily send List of objects to controller using Ajax. Am I doing something wrong?
In my controller, I have this method:
[HttpPost("EditMultipleResults")]
[Consumes("application/x-www-form-urlencoded")]
public bool EditMultipleResults([FromForm] List<Result>, [FromForm] string comment)
{
// do something...
return true;
}
Result is defined here
public class Result
{
[Key]
public long taskcd { get; set; }
public long Runno { get; set; }
public string Workorder {get; set;}
}
In my JS Ajax I have:
var results = [
{taskcd: 123,
Runno: 187776876,
Workorder: 'VA1234567'
},
{taskcd: 642,
Runno: 187776877,
Workorder: 'VA1234569'
},
{taskcd: 766,
Runno: 187776876,
Workorder: 'VA1234564'
}
];
var posteddata = {
results: results,
comment: 'test comment'
};
// call the controller
$.ajax({
type: 'POST',
data: posteddata,
traditional: true,
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
url: 'api/ResultsEditor/EditMultipleResults',
success: function () {
deferred.resolve();
},
error: deferred.reject
});
return deferred.promise();
My problem is that results list and reason are null when in controller. How can I pass a list of objects to controller in .NET Core 5?
Another question: is there a way to see the data that's being passed to controller in dev tools?
you can't use [FromForm] (as well as [FromBody]) multiple times, your action input parameter should be the same as it is in ajax, so you will have to create a class
public class PostedData
{
public List<ResultItem> Results { get; set; }
public string Comment { get; set; }
};
and action
public bool EditMultipleResults(PostedData data)
{
// do something...
return true;
}
and you don't need to use [Consumes("application/x-www-form-urlencoded")] ,[FromForm] and contentType: 'application/x-www-form-urlencoded; charset=utf-8' since all of them are already by default.
Because you are creating form data as a json object manually, instead of posting an html form, you need to encode that data as x-www-form-urlencoded manually also.
This post has some great suggestions. Make sure to read not just the accepted answer.
I would like to know which way is standard and normal.
I send a post http request with a lot of key and value pairs but I can send only one key and a json string object as a value. Which is more suitable
Thx
it depends on your backend : if it receives an object then use the second option {"myParamName:{"prop1":prop1,"prop2":prop2}}
If it receives several params then use option one
In my option use json syntax and send an object to the back : sending several params is good when you've got a few but what would you do when you need to send dozens ?
edit : As I see in your profile you use C# here is an example of ajax query to a .NET WEB METHOD :
$("#save").on('click', function (event) {
// setting the object of the back-end
var obj = {};
obj.Description = $("#Description").val().trim();
obj.Reference = $("#Reference").val().trim();
obj.Duration = $("#Duration").val();
obj.Begin = $("#Begin").val();
obj.End = $("#End").val();
obj.Id = $("#Id").val();
obj.Notes = $("#Notes").val().replace(/[\n\r]/g, '<br>');
obj.Done = $("#Done").val() == "true" ? true : false;
// to json format
var json = JSON.stringify({ "toDo": obj });
$.ajax({
type: "POST",
url: "Main.aspx/AddWork",
contentType: "application/json; charset=utf-8",
data: json,
success: function (response) {
// do what ever you want
},
error: function (jqXHR, textStatus, errorThrown) {
var str = jqXHR.responseText;
var obj = JSON.parse(str);
console.log(obj.Message);
} // end error
}); // end ajax
});
// on the back end : we receive an object named toDo of type Data
[WebMethod]
public static void AddWork(Data toDo)
{
...
}
// the Data type is declared in the same web method :
public class Data
{
public int Id { get; set; }
public string Description { get; set; }
public DateTime? Begin { get; set; }
public DateTime? End { get; set; }
public string Reference { get; set; }
public int? Duration { get; set; }
public bool? Done { get; set; }
public string Notes { get; set; }
}
// Hope it helps
Standard and normal is to just send plain application/x-www-form-urlencoded data. This approach has existed since long before JSON was designed and you can generate application/x-www-form-urlencoded data with a plain HTML form submission.
Encoding your data as application/json and then embedding it inside application/x-www-form-urlencoded creates more work to encode and decode the data, and adds more possible points of failure.
The only advantage that JSON offers is that it has native support for more complex data structures like arrays and objects… but extensions to the application/x-www-form-urlencoded format (supported by (at least) PHP, body-parser, and PHP::ParseStr) add that.
The option you didn't mention was just plain application/json which is popular with HTTP based APIs. It doesn't have the advantage of being compatible with a plain HTML form submission, but it doesn't have the complexity of embedding the two formats.
I want to send all the data from the DB as a json array to jsp to be fetched by ajax.
EmployeeController
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#RequestMapping(value = "/index", method = RequestMethod.GET)
public #ResponseBody List<Employee> listAllUsers() {
return employeeService.listEmployeess();
}
and the jsp
ajaxCall = function() {
$.ajax({
url : 'EmployeeController',
type : 'GET',
dataType : 'json',
error : function(that, e) {
alert(e);
},
success : function(data) {
alert(data);
}
});
}
so how to make this?
By Default your REST Controller converts java objects into JSON object out-of-the Box. But you can also use #Produces("application/json") above the controller method.
Please try to run the ajax response data in a loop data[i], if it doesn't work then use the dot invocation method to reach the data.
Here is my jQuery which looks at an HTML table and gets an id from the tr and an input field value and puts them in an object to be json stringified and posted to an MVC controller. I am using jQuery 1.8.2
var rowdata = [];
$('table').find('tr').each(function () {
myjson = [];
item = {}
item["id"] = $(this).attr('id');
item["reason"] = $(this).find('input').val();
myjson.push(item);
rowdata.push(myjson);
});
jsonstring = JSON.stringify(rowdata);
$.ajax({
url: '#Url.Action("AbsentReason", "Attendance")',
data: jsonstring,
type: 'POST',
traditional: true,
contentType: 'json',
success: function (data) {
$('#message').html("Reason was updated");
}
});
This is the resulting JSON which checks valid.
[[{}],[{"id":"6","reason":""}],[{"id":"7","reason":""}],[{"id":"15","reason":""}],[{"id":"23","reason":""}],[{"id":"29","reason":""}],[{"id":"30","reason":""}],[{"id":"31","reason":""}],[{"id":"35","reason":""}],[{"id":"40","reason":""}],[{"id":"41","reason":""}],[{"id":"42","reason":""}],[{"id":"48","reason":""}],[{"id":"49","reason":""}],[{"id":"50","reason":""}],[{"id":"51","reason":""}],[{"id":"52","reason":""}],[{"id":"53","reason":""}],[{"id":"54","reason":""}],[{"id":"55","reason":""}],[{"id":"56","reason":""}],[{"id":"57","reason":""}],[{"id":"58","reason":""}],[{"id":"59","reason":""}],[{"id":"60","reason":""}],[{"id":"61","reason":""}],[{"id":"62","reason":""}],[{"id":"63","reason":""}],[{"id":"74","reason":""}],[{"id":"75","reason":""}],[{"id":"80","reason":""}],[{"id":"81","reason":""}],[{"id":"87","reason":""}],[{"id":"88","reason":""}],[{"id":"90","reason":""}],[{"id":"91","reason":""}],[{"id":"105","reason":""}],[{"id":"106","reason":""}],[{"id":"107","reason":""}],[{"id":"108","reason":""}],[{"id":"110","reason":""}],[{"id":"111","reason":""}],[{"id":"119","reason":""}]]:
This is the start of my controller.
[HttpPost]
public ActionResult AbsentReason(string jsonstring)
{
return View("Index");
}
The jsonstring parameter is always null. Can anyone see what is wrong?
UPDATE
This is my new controller based on the comments to use a model and allow MVC to do the work for me.
[HttpPost]
public ActionResult AbsentReason(IEnumerable<VMAttendance> jsonstring)
{
return View("Index");
}
and my viewmodel
public class VMAttendance
{
public int PersonID
{
get;
set;
}
public string Reason
{
get;
set;
}
}
The parameter is still null. I also update my jQuery in an attempt to send the correct json.
var data = $('table').find('tr').map(function () {
var id = $(this).attr('id');
var reason = $(this).find('input').val();
var rowdata = { "PersonID": id, "Reason": reason };
return rowdata;
}).get();
$.ajax({
url: '#Url.Action("AbsentReason", "Attendance")',
data: data,
type: 'POST',
traditional: true,
contentType: 'json',
success: function (data) {
$('#message').html("Reason was updated");
}
});
I tried to send some test json to the controller but the parameter is still null.
var data = '{"PersonID":"6","Reason":""},{"PersonID":"7","Reason":""}'
assuming you have an MVC model as follow
public class MyModel
{
public int ID {get;set;}
public string Reason {get;set;}
}
if you modify your action method signature to
public ActionResult AbsentReason(IEnumerable<MyModel> json)
when you post back your json object, the json serializer will deserialize your json into an IEnumerable of MyModel.
I got this working by changing the contentType from 'json' to 'application/json; charset=utf-8' and removing the first empty object in my json which was created from an extra tr in the table for the header. The json looked like
[{},{"PersonID":"6","Reason":""},{"PersonID":"7","Reason":""}]
when it should look like this
[{"PersonID":"6","Reason":""},{"PersonID":"7","Reason":""}]
My controller looks like this and works nice.
[HttpPost]
public ActionResult AbsentReason(IEnumerable<VMAttendance> jsonstring)
{
return View("Index");
}
Thanks Duy for your assistance!
change the contentType in your ajax object to string.
i'm curious as to why you would want to treat your json as string and not as object. Normally I would have a C# viewmodel and let the serializer map the json object to that C# view model in my controller
I need to pass a JS object to my controller method jqGrid. The object is call "activeFilters" - here is the object represented as JSON:
{"family":
[{
"filterDisplayName":"Performance Status",
"filterDbName":"CurrentStatus",
"filterValueList":"On Plan"
}]
}
Having problems passing the above to my jqGrid (details further down). But I can pass the object to a controller with Ajax very simply:
$.ajax({
url: myMethodPath,
type: 'POST',
dataType: 'html',
data: JSON.stringify(activeFilters),
contentType: 'application/json; charset=utf-8',
success: function (result) {
alert("success")
},
error: function () {
alert("Error:");
}
});
My test controller method looks like:
[HttpPost]
public ActionResult DataTest(JsonFilterFamily activeFilters)
{
return PartialView();
}
Add the structure of JsonFilterFamily looks like:
public class JsonFilterFamily
{
public List<FilterFamilyMember> family { get; set; }
}
public class FilterFamilyMember
{
public string filterDisplayName { get; set; }
public string filterDbName { get; set; }
public string filterValueList { get; set; }
}
With the above Ajax, the JS object gets sent to the controller without problems. But I just can't figure out how to send the same JS object as the postData in a call to jqGrid controller. I must have the syntax wrong for post data. Here is what I am using:
$("#myJqGrid").setGridParam({ postData: { family: activeFilters.family} }).trigger("reloadGrid");
But when the controller fires, something strange happens. The debugger tells me the count of family = 1; but filterDisplayName, filterDbName, filterValueList are null. Any ideas on what is wrong?
In your controller method, try putting:
var filterFamilyMember = new FilterFamilyMember();
TryUpdateModel(filterFamilyMember);
TryUpdateModel is a MVC controller method and this will put the data in your object.