JSON - Spring MVC : How to post json data to spring MVC controller - json

I have a problem posting JSON data from jsp to controller. Everytime I try I get an ajax error Bad Request. Im so new to JSON and I really don't know what I am doing wrong. I searched and tried some samples I can find in this site but still Im having a problem.
In my controller:
#RequestMapping (method = RequestMethod.POST, headers ={"Accept=application/json"}, value = "/form")
public String postJournalEntry (#RequestParam ("json") String json, Model model) {
System.out.println(json);
return "successfullySaved";
}
In my jsp:
$("#btnPostGlEntry").click(function () {
var glEntries = '{"glEntries":[{"generalLedgerId":"1"},{"accountId":"4"},{"amount":"344.44"},{"description":"Test Entry"},{"debit":"Yes"}]}';
$.ajax({
type: "POST",
contentType: "application/json",
dataType: "json",
url: contextPath + "/generalLedger/journalEntries/form",
data : JSON.stringify(glEntries),
success: function(data) {
alert("Success!!!");
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR + " : " + textStatus + " : " + errorThrown);
}
});
});
NOTE : Im not even sure if my function in my controller is correct. I think my controller and my ajax are wrong. Please help.

If you want your JSON to be deserialized into some class, than you have to define method like this (and don't forget to add jsonConverter, as in previous answer):
.... method(#RequestBody MyClass data){ ... }
But, if you want your method to accept JSON as String than do this:
.... method(#RequestBody String json){ ... }
So, basically, if you post JSON, it means that JSON is not a parameter, it is body of the request. And eventually you have to use #RequestBody annotation, instead of #RequestParam.
You can find beautifull video tutorial of Spring Mvc and JSON here: sites.google.com/site/upida4j/example

it seems you dont have a Json Converter configured properly
like this one
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>

Related

Pass json data to ASP.Net core 2 web api

I know that this question has been asked several times, but none of the previous solutions helped me out with my problem (that seems a pretty simple one actually).
I just want to send a Json object to a Post method that I created in a controller class.
Here's the interesting portion of my controller class:
[Route("api/[controller]")]
public class CodeController : Controller
{
[HttpPost]
public void Post([FromBody] InfoNegozio value)
{
return;
}
}
I kept it simple as I just want the value to be set properly.
Here's the class InfoNegozio:
public class InfoNegozio
{
public int IdNegozio { get; set; }
public string NomeNegozio { get; set; }
public int AttesaStimata { get; set; }
public DateTime UltimoAggiornamento { get; set; }
}
This is the code used to send data to this API:
var myData = { "IdNegozio": idNegozio, "AttesaStimata": tempoAttesa };
$.ajax({
url: "api/Code",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(myData)
});
The JQuery code just call the webapi controller, the value field is a not null InfoNegozio object, but the field IdNegozio and AttesaStimata are always 0.
I could ask that I'm using a controller in a Razor Page project, and I had to add this line of code in the Startup.Configure method in order to make it work (with "it" I meant the other webapi GET methods).
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
Any Idea?
Edited
Using postman I figured out what the difference is between a wroking call and a not working one.
The posting this json with postman is works:
{
"IdNegozio": 1,
"AttesaStimata": 36
}
Unfortunately, with jquery, using JSON.stringify, I get this (note the double quote on the values):
{
"IdNegozio": "1",
"AttesaStimata": "36"
}
And this don't work!
Are Json stringify incompatible with .net core Web Api? Is it possible there isn't a clean approach to make those 2 libraries work together?
Edited 2
I ended up building the json manually, forcing jquery to sent "my version", so my js code is now looking:
var myData = '{ "IdNegozio": '+idNegozio+', "AttesaStimata": '+tempoAttesa+' }';
$.ajax({
url: "api/Code",
type: "POST",
contentType: "application/json",
dataType: "json",
data: myData
});
Anyway I don't like this solution as it seems I'm not using the right way to build the json object, so any smarter solution would be much appreciated.
Creating an answer so we don't have a million comments on your post. This is a ASP.NET Core 3.1 Web API project, correct ? If so, try making these couple of changes and see if that fixes the issue.
Inherit from ControllerBase rather than the full Controller class. Also add the [ApiController] attribute to your CodeController class. Then for your Post action, remove the [FromBody] attribute from your InfoNegozio parameter. Like this :
[Route("api/[controller]")]
[ApiController]
public class CodeController : ControllerBase
{
[HttpPost]
public IActionResult Post(InfoNegozio value)
{
return Ok(value);
}
}
See if that fixes anything. Something is getting screwed up during model binding, which leads me to believe that your JSON Serialization configuration is messed up. If you can post your Startup.cs, then we can see if there may be a configuration error. I just opened up a .NET Core 3.1 Web API project and tested one of my controllers and it works as expected. So give that a shot and see if maybe that fixes it. These items will affect how the controller is configured, so if it is an API controller, handling standard API requests (application/json) then it should be configured as such. You can read the specifics on the ASP.NET Core 3.1 docs but having this setup properly as an API Controller is going to make sure your JSON requests are properly serialized. Right now you have it set up like an MVC controller which is likely why you're running into issues.
Edit: Also, consider returning an IActionResult from your controller action. Might make testing easier as you can actually receive a response that will help you find the error. Then simply just change return; to return Ok(); Updated code sample to reflect this.
If you want to write like the first way you provided, you can use parseInt to ensure that int type data is passed.
Try this codeļ¼š
var myData = { "IdNegozio": parseInt(idNegozio), "AttesaStimata": parseInt(tempoAttesa) };
$.ajax({
url: "api/Code",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(myData)
});
There is also another choice (if you used core 3.x version):
Install Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.x
library
Add services.AddControllersWithViews().AddNewtonsoftJson(); in
ConfigureServices in startup.cs.
After these two steps, you can use the json format you used at the beginning.
var myData = { "IdNegozio": idNegozio, "AttesaStimata": tempoAttesa };
$.ajax({
url: "api/ApiCode",
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(myData)
});

Asmx response to json and call via ajax

I have the following problem
I am trying to connect a HTML page with a asmx service, using jquery.
The service is in my local IIS, and I have configured it for allow cross-domain request:
This is my service code:
[WebService(Namespace = "http://myservices.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class Test : WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Employee TestMethod()
{
return new Employee { Id = 1, Name = "John"};
}
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
This is my web.config service code:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<handlers>
<add name="ScriptHandlerFactory"
verb="*" path="*.asmx"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
resourceType="Unspecified" />
</handlers>
</system.webServer>
</configuration>
So, with that I can call to service method from anywhere (different domains) using this url
http://localhost/WsTest/Test.asmx/TestMethod
But, the response is in xml, why? ... I don't know what I need
<Employee xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://myservices.org/">
<Id>1</Id>
<Name>John</Name>
</Employee>
That is my first question.
Second, When I try to get the service response using ajax with the following code:
$.ajax({
url: "http://localhost/WsTest/Test.asmx/TestMethod",
beforeSend: function () {},
data: {},
contentType: "application/json; charset=utf-8",
type: "POST",
dataType: "jsonp",
processData: false,
cache: false,
success: function(data) {
alert(data)
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Retrieve Failed (AJAX Error): " + jqXHR.statusText + " | " + textStatus + " | " + errorThrown);
}
});
I get the following response:
TestMethod?callback=jQuery220045970173459500074_1454084649739&[object Object]&_=1454084649740:1
Uncaught SyntaxError: Unexpected token <
Retrieve Failed (AJAX Error): load | parsererror | Error: jQuery220045970173459500074_1454084649739 was not called
I have read several answers about this question, but i cannot find the appropriate answer for my problem.
Thanks in advance!
I think you are not properly serializing the response before sending it back to the client.
You have to make your class serializable into a Json string. To do that follow the instructions provided in the following MSDN link:
How to: Serialize and Deserialize JSON Data
Then, you should change your web method to return a String value, and just before returning the response to the client, do the serialization trick, something like this:
var objectSerializer = new JavascriptSerializer();
//serialization
return objectSerializer.Serialize(data); //this will return a Json string
For more details about the JavascriptSerializer class check out the following link:
JavaScriptSerializer Class
And about your error, it is because your response is returning in XML format (the standard SOAP response) thus the javascript code you are using is expecting a Json format. The trick is to simply return a Json string.
The other option you have is to use WCF instead of ASMX, but that is another path you can check out here:
How do I return clean JSON from a WCF Service?
Beware about the security risks involved in exposing your service like that. Use unique ids or other mechanisms to secure your web service invocations from Javascript.

REST #Context UriInfo is empty

I have the following code snippet which I have to use pass data to server
function myFuntion() {
var myurl = 'myurl/';
var mydata = $("#myform").serializeArray();
$.ajax({
url: myurl,
type: 'POST',
contentType : "application/json; charset=utf-8",
dataType: 'json',
data: mydata,
success: function (data) {
...
}
});
}
and in server JERSEY code
#POST
#Path("/persistlogs")
public Object myMethod(#Context
UriInfo uriInfo) {
MultivaluedMap params = uriInfo.getPathParameters();
params.size() // is always null
Issue is uriInfo is always null
What could be the reason for this?
UriInfo is mainly used to get information form the URI/URL. getPathParameters() return a Map of key value pairs where the key is a string extracted from URI templates in #Path. For instance #Path("{id}") would put the id as a key, and its value as the key value.
That being said, you don't want any information from the URI. What you want is the request body content. With application/json, generally we can use POJOs to model the incoming data (as described here). You will need to make sure you have a JSON provider to handle the JSON to POJO deserialization. For help with that, I would need to know what Jersey version you are using (you can comment below if you need help).
Just to see the data coming in (without POJO conversion), you can just have a String parameter, and the deserialization will pass the JSON as a String to the method
#POST
#Path("/persistlogs")
#Consumes("application/json")
public Object myMethod(String jsonData) {
System.out.println(jsonData);
}
As for sending the data, I would avoid using the .serializArray() for the form. You are going to be left with JSON like
[
{
"name": "...",
"value": "..."
},
{
"name": "...",
"value": "..."
}
]
It's not very pretty to work with, as you will need something like Pair class, which really has no semantic value. Better to just create a POJO that maps a Javascript model object to a Java object. This is also described in the first link.
UPDATE
for Jersey (1.x) JSON support, add the following Maven dependency
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.17.1</version>
</dependency>
Then in your web.xml, configure the JSON support.
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>

Returning JSON with web api controller MVC

I am trying to convert a regular old controller I was using to an API controller and am having a little bit of difficulty. What these series of functions do is, in the jQuery, it iterates over a file containing all the usernames of employees and for each username it makes a call to the PopulateEmployee method in my webapi controller which should return JSON and then populate a results div.
When manually navigating to
..domain../staffinformation/populateemployee/employeeusername
I get the error
This XML file does not appear to have any style information associated with it. The
document tree is shown below.
<Error>
<Message>
The requested resource does not support http method 'GET'.
</Message>
</Error>
Please note that the div it will be populating is a partial view in an Umbraco CMS page and I don't think that is the problem but if you guys think differently please tell me.
There has to be something I am missing either with webAPI routing or something else.
Thanks for your help.
Here's the codez.
Please notice that this method has the HttpPost tag
public class StaffInformationController : ApiController
{
[System.Web.Http.ActionName("PopulateEmployee")]
[System.Web.Http.HttpPost]
public StaffListing PopulateEmployee(string id)
{
//do error checking on input
StaffListing staffListing = new StaffListing(id);
//populate other fields
return staffListing;
}
}
The routing set up for the api controller
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
The jQuery call specifying use of 'POST', please forgive the trickiness of the recursive call in this function.
function getEmployeeObjectByIndex() {
$.ajax({
url: $('#root').val() + '/api/StaffInformation/PopulateEmployee',
type: 'POST',
async: true,
contentType: 'application/json, charset=utf-8',
data: JSON.stringify({ 'username': lines[i] }),
success: function (staffObject) {
if (!(staffObject.Name == undefined)) {
buildHtmlStrings(staffObject);
}
i++;
getEmployeeObjectByIndex(); //recursive call
}
});
}
manually navigating to that address throws the error because, when manually navigating you are doing a GET (and your method only allows POSTs).
You should fire up Fiddler and watch the ajax POST request and response to see how the server is responding / your request is being made
Jquery ------> web api
Web API has one property i.e. CONTENT NEGOTIATION means you send any data and accept any data as you want.
$.ajax({
contentType: 'application/json, charset=utf-8',
// this is sending your data of datatype json to server, here you send any type of data
accept: 'application/json',
//this is receiving/getting data form server to client...
// SO HERE YOU GET JSON DATA AS YOU WANT only mention which data of datatype u want...
//if you sending xml and you want json so only write accept as json it get automatically converted into your required datatype..by MediaTypeFormatter
});

Return JSON from ASMX web service, without XML wrapper?

I need to get Json data from a C# web service.
I know there are several questions based on this, trust me I have read through quite a few but only to confuse me further.
This is what I have done :
In my web service I have included : [System.Web.Script.Services.ScriptService] for the class & [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] for the method
I have also used a JavaScriptSerializer() to convert my data to a string
I am calling this service using $.getJSON()
If I don't use that I get an Cross domain reference error.
To do this I had to setup m service to get the callback function name
so I am passing this.Context.Request["callback"] + serialized Json Data;
But in the output I get it wrapped in
< string xmlns="http://XYZ...">
The data within the tags is in the format I need
I also tried setting content type using : $.ajaxSetup({ scriptCharset: "utf-8" , contentType: "application/json; charset=utf-8"});
But still no success.
Addded later: I accepted frenchie's anwser beacuse I know it is the correct approach but I stil cud not get it to work... I just put the webservice & website in the same domain & used xml, I know it wasnt the best way, but I had spent 2 days on it & could not afford to waste more.
Use this:
var JsonString = ....;
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "YourWebServiceName.asmx/yourmethodname",
data: "{'TheData':'" + JsonString + "'}",
dataType: "json",
success: function (msg) {
var data = msg.hasOwnProperty("d") ? msg.d : msg;
OnSucessCallBack(data);
},
error: function (xhr, status, error) {
alert(xhr.statusText);
}
});
function OnSuccessCallData(DataFromServer) {
// your handler for success
}
and then on the server side, in the code behind file that's auto-generated in your AppCode folder, you write something like this:
using System.Web.Services;
using System.Web.Script.Serialization;
[System.Web.Script.Services.ScriptService]
public class YourWebServiceName : System.Web.Services.WebService
{
[WebMethod]
public string yourmethodname(string TheData)
{
JavascriptSerializer YourSerializer = new JavascriptSerializer();
// custom serializer if you need one
YourSerializer.RegisterConverters(new JavascriptConverter [] { new YourCustomConverter() });
//deserialization
TheData.Deserialize(TheData);
//serialization
TheData.Serialize(TheData);
}
}
If you don't use a custom converter, the properties between the json string and the c# class definition of your server-side object must match for the deserialization to work. For the serialization, if you don't have a custom converter, the json string will include every property of your c# class. You can add [ScriptIgnore] just before a property definition in your c# class and that property will be ignored by the serializer if you don't specify a custom converter.