returning json object from controller to jsp - json

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.

Related

How Controller convert JSON data from AJAX to Model instance?

Just out of curiosity. I observed that when I make POST method in AJAX. I always mention datatype:'json' and it actually works with my model instance in parameter in Controller - The URL path mentioned in AJAX. But, at the same time when I was sending data to JQGrid I needed JSON return type controller to send data in JSON format.
How could model type method can auto-adjust itself with JSON format data?
For Using jqGrid With ASP.NET MVC
https://www.c-sharpcorner.com/article/using-jqgrid-with-asp-net-mvc/
Model
public class ExampleModel
{
public int Id { get; set; }
public string Text { get; set; }
}
Ajax Example
var model = { Id :12, Text :"Testing Data"};
$ajax({
type: 'POST',
dataType: 'json',
url:'/ExampleController/ExMethod',
data:{'exampleModel' : model},
success: (result) =>{
console.log(result);
},
error : (error) =>{
console.log(error);
}
}}
Controller
[HttpPost]
public string ExMethod(ExampleModel exampleModel){
return null;
}

Spring MVC - RequestBody not working (JSON)

I'm having a simple controller method:
#RequestMapping(value = "/test", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(value = HttpStatus.OK)
#ResponseBody
public void postCheck(#RequestBody TestDTO testDTO, HttpServletRequest request) {
System.out.println(testDTO);
}
the DTO is:
public class TestDTO {
private String hello;
public TestDTO() {
}
public String getHello() {
return hello;
}
public void setHello(String hello) {
this.hello = hello;
}
}
When i try to post a request to that url i get an ERROR 400 Message response "The request sent by the client was syntactically incorrect." (the controller method is not being invoked at all)
I tried posting from Chrome's poster plugin AND from jquery's ajax:
$.ajax({
type : "POST",
url : "http://localhost:8080/NG_Admin/test",
contentType : "application/json",
dataType : "json",
data : JSON.stringify(eval({"hello" : "world"})),
error : function(data) {
alert('Error');
},
success : function(data) {
alert('Success!');
}
});
}
Any ideas? (btw I use both 'jackson-mapper-asl', version:'1.9.12', 'jackson-core-asl', version:'1.9.12')
Thanks
OK,I fixed the problem,
Had to add a filter for all request that handles CORS access.

JSON posted to MVC Controller is null

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

Using json.net serializer in webmethod

I'll start from my problem:
I have a webmethod that I'm calling via AJAX/JSON.
Let's call it "GlobalMethod", that's used to manage a "container" object, that has a list of items derived from the same "baseclass".
This is a code sample of my situation:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public string GlobalMethod(Container data)
{
string result = "";
foreach (var item in data.Items)
{
result += item.BaseProperty;
if (item is FirstDerivedClass)
result += ((FirstDerivedClass)item).FirstDerivedProperty;
else if (item is SecondDerivedClass)
result += ((SecondDerivedClass)item).SecondDerivedProperty;
}
return result;
}
}
public class Container
{
public List<BaseClass> Items;
}
public abstract class BaseClass
{
public string BaseProperty;
}
public class FirstDerivedClass : BaseClass
{
public string FirstDerivedProperty;
}
public class SecondDerivedClass : BaseClass
{
public string SecondDerivedProperty;
}
This method simply doesn't work out. I won't be able to call this method using the default JavascriptSerializer, as the serializer isn't able to resolve what kind of objects the container will have: they could be of type FirstDerivedClass or SecondDerivedClass.
So, browsing the web for solutions to my problem, I've come across Json.NET, whose method JsonConvert.DeserializeObject is able to retrieve the original type of object that was serialized using the JsonConvert.SerializeObject, since it adds a property called "$type".
My problem now is: how can I make the webmethod using this serializer instead of the default one used by the ASMX?
If the method signature remains
[WebMethod]
public string GlobalMethod(Container data)
then I'll get a totally empty Container object, as the framework is doing the deserialization job and doesn't know which items to instantiate, and I have no way of telling the framework that it should use Json.NET for the job, which would be able to fully deserialize the data.
If I try modifying the method this way
[WebMethod]
public string GlobalMethod(string data)
{
string result = "";
Container container = JsonConvert.DeserializeObject<Container>(data,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
foreach (var item in container.Items) {
...
then I'll get another server error 500 because "no parameterless constructor defined for type of u0027system.string u0027"
Ok, hopefully my problem is clear... I've been spending the entire day on it and I don't seem to find a solution. Revisiting the architecture of my method in order to avoid usage of derived classes isn't quite an option (beware the actual code is much more complex, I've just simplified it to get to the point!).
By the way, I'll add that the ajax method calling the webmethod is done this way:
$.ajax({
type: "POST",
url: wsUrl + method,
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: "json",
processData: false,
success: function(msg)
{
try{
success(JSON.parse(msg.d));
} finally {
}
},
error: error
});
Thanks to anybody who will share his knowledge with me!
I'd like to share how I actually solved my problem. As I was already saying, I modified my method this way:
[WebMethod]
public string GlobalMethod(string data)
{
string result = "";
Container container = JsonConvert.DeserializeObject<Container>(data,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
foreach (var item in container.Items) {
Initially, I started receiving the error 500 "no parameterless constructor defined for type of u0027system.string u0027"
But eventually I found out the reason: the json string that was travelling from client to server was being deserialized by the .NET framework into the contained object, which wasn't a string, but an actual JSON object!
So the trick was the following, in my ajax method:
$.ajax({
type: "POST",
url: wsUrl + method,
**data: JSON.stringify(JSON.stringify(data)),**
contentType: "application/json; charset=utf-8",
dataType: "json",
processData: false,
success: function(msg)
{
try{
success(JSON.parse(msg.d));
} finally {
}
},
error: error
});
which means that the json object is encapsulated inside another string, which will be manually deserialized by my server-side GlobalMethod(string), through Json.NET.
Obviously I won't be including this double "stringify" in the ajax routine, but I'll pay attention to pass a JSON.stringified data in input to the ajax routine itself!
This is just an hack,
it's just an idea, doesn't sound elegant but it should work
I'm just curious
change the container in this way:
public class Container
{
public List<MyUnionBaseClass> Items;
}
and define (pseudocode):
public class MyUnionBaseClass{
public void MyUnionBaseClass(BaseClass b){
this.setValue(b);
};
final public BaseClass getValue(){
if(first!=null) return (BaseClass) first;
if(second!=null)return (BaseClass) second;
return null;
}
final public setValue(BaseClass b){
if(b instanceOf firstClass){
first = (FirstClass) b;
}
if(b instanceOf secondClass){
second = (SecondClass) b;
}
}
private FirstDerivedClass first=null;
private SecondDerivedClass second=null;
}
P.s: this is very rought and should be improved.
Does this make sense?
Change the webmethod to accept an object
[WebMethod]
public string GlobalMethod(object data)
This should resolve the issue you are having.

jqGrid: how to pass complex javascript object as postData to ASP MVC controller method

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.