Passing list of object from client to Spring controller - javascript

I am facing an issue while retrieving data from client to controller.
I got 400 Bad Request error and I cannot find the reason for it.
I am using dojo gridx here and this is the js file
function goToReviewTargetsPage(){
var gridSelectedData = JSON.stringify( dijit.byId("geneGridNodeforSelectTargets").store.data);
dojo.xhrPost({
url : contextPath + '/updateGeneData.htm',
handleAs: 'json',
headers: {
'Content-Type': 'application/json',
},
applyAroundAdviceOnLoad : true,
preventCache : true,
content :
{
"selectedTargetsData" : gridSelectedData
},
load : function(data)
{
\\do something
},
error : function(error)
{
hideLoadingDialog();
}
});
}
The json data in gridSelectedData mentioned in above js is:
[{"id":1,"name":"ABL1","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":true,"CNV":true,"SNP":true},{"id":2,"name":"ALK","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":false,"CNV":true,"SNP":true},{"id":3,"name":"BLA","diseases":[{"id":1,"diseaseName":"CANCER"}],"SV":false,"CNV":false,"SNP":true},{"id":4,"name":"ALS","diseases":[{"id":2,"diseaseName":"LUNGS"}],"SV":false,"CNV":true,"SNP":true}]
This is the code from the controller
#RequestMapping(value = "/updateGeneData", produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody Gene[] genes,
HttpServletResponse response, HttpServletRequest request)
{
List<Gene> geneList = new ArrayList<>();
// do something
return geneList;
}
Gene.java (POJO)
public class Gene {
private Integer id;
private String name;
private boolean SNP = false;
private boolean SV = false;
private boolean CNV = false;
Set<Disease> diseases = new HashSet<Disease>();
//getters and setters
}
This is the Request Header
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.9
ajaxRequest:true
Connection:keep-alive
Content-Encoding:UTF-8
Content-Length:795
Content-Type:application/json
X-Requested-With:XMLHttpRequest
The payload is:
[{id: 1, name: "ABL1", diseases: [{id: 1, diseaseName: "CANCER"}], SV: true, CNV: true, SNP: true},…]

change the post request from /updateGeneData.htm on /updateGeneData and delete attributes produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE,

Your controller is wanting an array [] and you're passing it a list. Your controller should be
#RequestMapping(value = "/updateGeneData",
produces MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE,
method = RequestMethod.POST)
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody List<Gene> genes) {
List<Gene> geneList = new ArrayList<>();
// do something
return geneList;
}
I have found that sometimes I need to wrap my DTO in order for Jackson to work. This approach as worked for me in the past.
class Genes extends ArrayList<Gene> { }
#ResponseBody
public List<Gene> getSelectedGenes(#RequestBody Genes genes) {

Related

BAD Reuqest Cannot create and populate list type Microsoft.AspNetCore.Http.IFormFileCollection

I am receiving Bad request when uploading my file and converting it into json and passing to my .net core webapi controller.
here its an error screenshot.i have also console the model as well.
here its my code in typescript
const httpHeaders = new HttpHeaders({
'Content-Type': 'application/json',
});
var approval = {
...this.MemberApproval,
};
console.log(JSON.stringify(approval));
return this.http.post(this.Url + '/Member/UpdateMember/update', JSON.stringify(approval), { headers: httpHeaders });
on .net core webapi i am doing like this.
My model :
public class MemberApproval
{
public string Notes;
public IFormCollection Attachment;
public int ApprovalStatus;
public int SubsId;
public int MemberId;
}
My controller :
[Route("[action]/{item}")]
[HttpPost]
public IActionResult UpdateMember([FromBody]MemberApproval approval )
{
if (approval !=null)
{
_repo.UpdateMemberStatus(approval);
}
return Ok();
}
If you want to submit a file to ASP.Net Core you have to use FromForm and IFormFile like this
[HttpPost("SavePost")]
public async Task<IActionResult> SavePost([FromForm]PostViewModel viewModel)
{
var postOptionsViewModel = _jsonParsePostOptionDefaultVm.ToObject(viewModel.PostOptionsViewModel);
viewModel.PostOptionsDefaultViewModel = postOptionsViewModel;
if (viewModel.Id.HasValue)
{
await _postRepository.EditPost(viewModel);
}
else
{
await _postRepository.SavePost(viewModel);
}
return Ok();
}
My model will have property List so you can submit multi file to server
public List<IFormFile> File { get; set; }
My FE side code will be like this. I'm using react but mostly not different in the way we submit a formdata to server
const formdata = new FormData();
formdata.append("Title", this.state.title);
formdata.append("File", this.state.File);
Remember to set Content-Type header to 'multipart/form-data'

How to put a javascript array inside an arraylist of a class object?

I have the following code:
Advertisement class:
public class Advertisement {
String name;
String description;
Date date;
String city;
String type;
int rooms;
int surface;
int price;
int userID;
ArrayList<String> images;
int httpStatus;
}
Advertisement spring controller:
#RequestMapping(value = "/post", method = RequestMethod.POST)
public boolean postAds(#RequestBody Advertisement newAd) {
System.out.println(newAd.name+" "+" "+newAd.rooms+" "+newAd.surface+" "+newAd.price+" " + newAd.type+" "+newAd.description+newAd.images);
return true;
}
Angular controller:
$http({
method: 'POST',
url: AppSettings.getApiUrl('/post'),
data: {
name: $scope.form.name,
description: $scope.form.description,
//city: $scope.form.city,
rooms: $scope.form.rooms,
surface: $scope.form.surface,
price: $scope.form.price,
type: $scope.form.selected,
images: $scope.images,
//userId: localStorage.getItem('token'),
}
Now, when I make the post request to the server it gives the following error:
JSON parse error: Cannot deserialize instance of java.lang.String out of START_ARRAY token; nested exception
How should I deserialize the $scope.images array into images?

jQuery.get from Spring RestController

How can should I send the data from Spring controller to the client? Do I need to wrap it as Json or is there an easier way?
(noob in web. So, please bear with me)
#RequestMapping("/abc")
#RestController
public class ListController {
#RequestMapping(value = "/d", method = RequestMethod.GET)
public StringOrJson? getData() {
return "myData";
}
On the client:
function checkBoxToggled(){
$(document).get('abc/d', function( data ) {
alert('Data Loaded2:' + data );
});
}
It will be great if you declare the #RequestMapping as follows:
#RequestMapping(value = "/d", method = RequestMethod.GET, produces = "application/json")
You can return simple String response.
Or you can always reutrn JSONObject as follows:
return new JSONObject("{'data':'myData'}");
In that case the return value in the method signature should be replaced to JSONObject.
You just need to modify your Controller to:
#RequestMapping("/abc")
#Controller
public class ListController {
#RequestMapping(value = "/d", method = RequestMethod.GET)
public String getData() {
return "myData";
}
}
And the client should be:
jQuery.get("abc/d", function (data) {
alert('Data Loaded2:' + data );
});

Pass json object to mvc4 controller - array passed as Nothing

I have searched and found quite a few results on this but none of them seemed to work. I can see there are values in params.list array (as shown below by console.log) but in the controller ZoneDataList is "Nothing" although vm.farmId, vm.cropPlanId and vm.taskId have data in the Controller.
What am I doing wrong?
Here's my code:
Javascript:
var zonedataArray = [];
var zoneInfo = {};
var params = { farmId: localStorage.FarmId, cropPlanId: selectedCrpPlanId, taskId: taskId, list: [] };
for (i = 0; i < viewModel.nutZoneRows().length; i++) {
zoneInfo = { "Rate": viewModel.nutZoneRows()[i].Rate(), "TotalAmount": viewModel.nutZoneRows()[i].TotalAmount() };
zonedataArray.push(zoneInfo);
params.list.push(zoneInfo);
}
for (i = 0; i < params.list.length; i++) {
console.log("params.list[i].Rate: " + params.list[i].Rate);
}//has correct values
$.ajax({
contentType: 'application/json',
url: '#Url.Action("SaveNutritionTask", "CropPlans")',
type: "POST",
dataType: "json",
data: JSON.stringify(params),
traditional: true,
success: function (result) {
$.mobile.loading('hide');
},
error: function (xhr, ajaxOptions, thrownError) {
$.mobile.loading('hide');
} //error
}); //ajax
}; //self.SaveCropPlan
Controller method:
<HttpPost()>
Public Function SaveNutritionTask(vm As CropPlanModel.CompleteZoneData) As JsonResult
End Function
Model:
Public Class CompleteZoneData
Public Property farmId As Guid
Public Property cropPlanId As Guid
Public Property taskId As Guid
Public Property ZoneDataList As List(Of ZoneData)
End Class
Public Class ZoneData
Public Property Rate As String
Public Property TotalAmount As String
End Class
you might need to use a model binding attribute for binding json (this is a c# implementation that you might need to translate to VB)
public class FromJsonAttribute : CustomModelBinderAttribute
{
private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
public override IModelBinder GetBinder()
{
return new JsonModelBinder();
}
private class JsonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
if (string.IsNullOrEmpty(stringified))
return null;
return serializer.Deserialize(stringified, bindingContext.ModelType);
}
}
}
and the modify your controller function like
<HttpPost()>
Public Function SaveNutritionTask([FromJson]vm As CropPlanModel.CompleteZoneData) As JsonResult
End Function
Found the problem. list in params in the javascript code should be renamed to ZoneDataList to match the Class name.

AngularJS $http / .NET Web API - Either Getting 400 (Bad Request) or NULL POST Action Method Parameter

Here’s a brief (as I can make it) description of my problem, along with all relevant code. I'm hoping the wording for this post will be a bit clearer than my previous request for assistance.
I have a .NET Web API, and an AngularJS front end. I have a very simple POST method which accepts a parameter of the ‘Envelope’ type, shown here:
public class Envelope {
public int listingId { get; set; }
public string Description { get; set; }
public override string ToString() {
return listingId.ToString() + "; " + Description;
}
}
The actual POST method on the API appears here:
[EnableCors(origins: "http://simpleapiearl.azurewebsites.net", headers: "*", methods: "*")]
public class EnvelopesController : ApiController {
// POST: api/Envelopes
public string Post(Envelope env) {
return "rval: " + env.ToString() + " (and my addition to env)";
}
}
My front-end AngularJS $http POST looks like this:
$scope.testPOST = function () {
var env = {
listingId:1234,
Description:"some desc"
};
$http({
method: 'POST',
url: 'http://simpleApiEarl.azurewebsites.net/api/envelopes',
data: JSON.stringify(env),
headers: {
'Content-Type': 'application/json'
}
}).
success(function (data, status, headers, config) {
$scope.postStatus = 'success: ' + data;
}).
error(function (data, status, headers, config) {
$scope.postStatus = 'error: ' + status;
});
}
Here are my issues (numbered for easier reference):
Using all the code as shown above, I get a “400 (Bad Request)” when I call “testPOST()” from my page. This sounds like a .NET Web API routing issue, but I can’t figure out what it is.
I can avoid the 400 (and in fact get a 200) if I change the ‘Content-Type’ header to ‘application/x-www-form-urlencoded’. HOWEVER, that results in the API seeing the ‘env’ parameter as NULL.
I tend to adorn my action method parameter with a ‘[FromBody]’ attribute, but doing so does not fix the problem of ‘env’ being NULL in my API action method.
I have created a simple plunk with my very simple HTML page used to call the API. It can be found here:
http://plnkr.co/edit/hY2OUeg9CRQ1QOz8MGU8?p=info
Thanks very much for any assistance you can provide.
'Content-Type': 'application/x-www-form-urlencoded'
This will work.
This is Controller:
public async Task<HttpResponseMessage> GetData(int pageNo, int pageSize)
{
HttpResponseMessage response = null;
int totalPage, totalRecord;
totalRecord = db.Employees.Count();
totalPage = (totalRecord / pageSize) + ((totalRecord % pageSize) > 0 ? 1 : 0);
var record = (from a in db.Employees
orderby a.id
select a).Skip((pageNo - 1) * pageSize).Take(pageSize).ToList();
DataWithPaging data = new DataWithPaging
{
PageNo = pageNo,
PageSize = pageSize,
TotalPage = totalPage,
TotalRecord = totalRecord,
EmployeeData = record
};
response = Request.CreateResponse(HttpStatusCode.OK, data);
return await Task.FromResult(response);
}
You should have a class named: DataWithPaging
public class DataWithPaging
{
public int PageNo { get; set; }
public int PageSize { get; set; }
public int TotalPage { get; set; }
public int TotalRecord { get; set; }
public List<Employee> Employees { get; set; }
}

Categories