Javascript xhr post body containing two objects as one - javascript

I am trying to send two objects to a web api (ASP.NET) , User and House.
Initially, I tried to send them as xhr.send(User,House), but I realized you can only send one object per body.
So, I created a wrapper class to contain both of the objects
public class Wrapper
{
public House house{ get; set; }
public User user{ get; set; }
}
However, when I send the json body into the api, the data receives the data object as null.
What am I doing wrong?
Front End :
var xhr = new XMLHttpRequest();
var url = "api_call";
xhr.open('POST', url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
var house = JSON.stringify({address : address, zip : zip});
var user = JSON.stringify({Email: email, Password: "aaaAAA1!"});
var wrapper = JSON.stringify({house : house, user : user});
...
xhr.send(wrapper);
Back End:
public async System.Threading.Tasks.Task<HttpResponseMessage> ApiCall(Wrapper wrapper)
{
// wrapper.house and wrapper.user is null
House house = wrapper.house;
User user= wrapper.user;
...
}

As our conversation as comment,
There is no need to stringify house and user, just stringify wrapper is enough , so initiate house and user to wrapper as object not string, the correction would be something like :
var xhr = new XMLHttpRequest();
var url = "api_call";
xhr.open('POST', url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
var wrapper = JSON.stringify({house : {address : address, zip : zip}, user : {Email: email, Password: "aaaAAA1!"}});
...
xhr.send(wrapper);

Related

Miagration Asp.Net Core 2 to .Net 6 gave me XMLHttpRequest problems

I folks, I just migrated my ASP.Net Core 2 MVC app to .Net 6, but since that, I have a weird problem: my XMLHttpRequest responses texts are always empty, "{}" or [{},{},{},{}] for arrays, despite my backend really returning data.
Here's an example of a controler method (TestLoad) returning a simple class (TestClass). Notice that when I break on the return line, the value returned is ok, or at least I don't see anything wrong (see image for debug infos):
backend
public class TestClass
{
public int id = 0;
public string title = "Title";
public bool active = false;
}
public JsonResult TestLoad()
{
TestClass testClass = new TestClass();
testClass.id = 10;
testClass.title = "Yeah man!";
testClass.active = true;
JsonResult jsonRes = Json(testClass);
return jsonRes;
}
But once on the front end, I got an empty object, not undefined nor null, but really an empty object (see image for debug infos):
frontend
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
var dt = JSON.parse(xmlhttp.responseText);
if (dt == 'err') {
alert('error');
}
else if (dt !== null) {
alert(dt.title);
}
}
else {
alert(xmlhttp.status);
}
}
}
ldwait(false, false);
xmlhttp.open("GET", rv + "ajxGame/TestLoad", true);
xmlhttp.setRequestHeader('Cache-Control', 'no-store');
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send();
Any help would be greatly appreciated since I completely clueless of what happened. Again, my code hasn't changed, but my project has migrated from .Net Core 2 to .Net 6.
Thank you
i would add a response type, and replace onreadystatechange with onload
xmlhttp.responseType = 'json';
xmlhttp.onload = () => {
console.log("load - "+ JSON.stringify(xhr.response));
var data = xhr.response;
}
Are you using Razor pages in your Asp.net core 6 ?
If so, the way you call your method maybe the issue. For post requests, call from the client ?handler=TestLoad and on the server make sure the method name is OnPostTestLoad().
Get requests are disabled by default and need to be enabled.
Microsoft Warning Message
For more info, check this link from Microsoft docs
Another issue maybe the way you return your class. Try returning it as a JSON object instead.
return new JsonResult(new {objClass: testClass});
And on the client side, get your class as an object property
let objClass = result.objClass;
Actually, my error was simply that I forgot to add { get; set; } on each property of my TestClass in the backend part! It worked without it in .Net Core 2, but it seems like this is now mandatory in .Net 6
public class TestClass
{
public int id {get; set;} = 0;
public string title {get; set;} = "Title";
public bool active {get; set;} = false;
}
...thanks to those who attempted an answer!

Ajax send JSON object with two arrays to a servlet and parsing in java servlet without jQuery

I have to send to a servlet two arrays, i use an Ajax POST call that sends a JSON object, and then I have to read the data sent in two lists or arrays in a servlet class in java.
I prefer not to use jQuery for Ajax call.
I am not very familiar with json, i used some code found in stackoverflow and i can't understand if there is a problem in sending or parsing data.
Here is the method to make the Ajax call in Javascript, where cback is the callback function, method = "POST" and url is the url of the servlet:
function makeCall(method, url, from, to, cback) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
cback(req)
};
req.open(method, url);
var obj = {};
obj["from"] = from;
obj["to"] = to;
var data = JSON.stringify(obj);
req.send(data);
}
Here is the doPost method in the servlet controller specified by the url. Here is where i found the problem: after doing getParameter, strings json1 and json2 are null:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//...
String json1 = request.getParameter("from");
String json2 = request.getParameter("to");
Gson gson = new Gson();
ArrayList<Double> listFrom = gson.fromJson(json1,
new TypeToken<ArrayList<Categoria>>() {}.getType());
ArrayList<Double> listTo = gson.fromJson(json2,
new TypeToken<ArrayList<Double>>() {}.getType());
//...
}
Your ajax is sending JSON but your servelet is expecting form data, that has JSON in it.
To send the data like your server expects encode each array to JSON and send them as form data
function makeCall(method, url, from, to, cback) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
cback(req)
};
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.open(method, url);
var params = new URLSearchParams({to: JSON.stringify(to), from: JSON.stringify(from)});
req.send(params.toString());
}

ASP.NET JavaScript - Invalid JSON primitive

I am trying to use "contentTools" with ASP.NET C# Website. I am trying to send the modified json to server side to store within database.
I have validated the JSON though external web but here is my code. For test purpose, I am trying to invoke an alert with a string sent back from my ASP.NET method.
window.onload = function () {
//ShowCurrentTime();
var FIXTURE_TOOLS, IMAGE_FIXTURE_TOOLS, LINK_FIXTURE_TOOLS, editor;
ContentTools.IMAGE_UPLOADER = ImageUploader.createImageUploader;
ContentTools.StylePalette.add([new ContentTools.Style('By-line', 'article__by-line', ['p']), new ContentTools.Style('Caption', 'article__caption', ['p']), new ContentTools.Style('Example', 'example', ['pre']), new ContentTools.Style('Example + Good', 'example--good', ['pre']), new ContentTools.Style('Example + Bad', 'example--bad', ['pre'])]);
editor = ContentTools.EditorApp.get();
editor.init('[data-editable], [data-fixture]', 'data-name');
editor.addEventListener('saved', function (ev) {
var name, payload, regions, xhr;
// Check that something changed
regions = ev.detail().regions;
if (Object.keys(regions).length == 0) {
return;
}
// Set the editor as busy while we save our changes
this.busy(true);
// Collect the contents of each region into a FormData instance
payload = new FormData();
payload.append('regions', JSON.stringify(regions));
xhr = new XMLHttpRequest();
xhr.open('POST', 'Default.aspx/getJSONHTMLResponse');
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
xhr.send(payload);
});
Here is my server-side:
[System.Web.Services.WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string getJSONHTMLResponse(string name)
{
return "Success";
}
And here is what I see in Developers tool in chrome as Request Payload:
------WebKitFormBoundaryilrxnMxm7ANdiYMp
Content-Disposition: form-data; name="regions"
{"para-1":"<p>\n testestest\n</p>","para-2":"<p>\n testestestestest.\n</p>"}
------WebKitFormBoundaryilrxnMxm7ANdiYMp--
And the error:
{"Message":"Invalid JSON primitive: ------WebKitFormBoundaryilrxnMxm7ANdiYMp.","StackTrace":" at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.ArgumentException"}
Just because you are accepting a string as a parameter from you api endpoint, send it as a string. No need to append into a FormData. That will send your payload as an object.
xhr.send(JSON.stringify(regions));
So I want to report back on how I resolved this issue.
Apparently I found out the hard way, form-data is tricky to be read. What I did instead:
Create a proper Web-service controller to accept a JToken response.
Parse the response in Key, Value pair.
Add it to a Session object and database as required.
Thanks!!

How to pass multiple parameters to #RequestBody using JavaScript XMLHttpRequest

I have that POST method:
function saveSchemaInDatabase(schemaName) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
};
xhttp.open("POST", "/user/saveSchemaInDatabase", true);
xhttp.send(schemaName);
}
and i am catching that shoot in my controller in that way:
#PostMapping(path = { "/user/saveSchemaInDatabase" })
public String saveSchemaInDatabase(#RequestBody String schemaName) {
return "redirect:/user";
}
Can someone tell me how i can send multiple params to that controller? For example i want something like that:
//shoot
function saveSchemaInDatabase(schemaName, diagramJson) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
};
xhttp.open("POST", "/user/saveSchemaInDatabase", true);
xhttp.send(schemaName, diagramJson);
}
//catch
#PostMapping(path = { "/user/saveSchemaInDatabase" })
public String saveSchemaInDatabase(#RequestBody String schemaName, #RequestBody String diagramJson) {
return "redirect:/user";
}
I hope you know what i mean. Of course my way doesn't work. Error 400 appears.
Can someone help me? Im done :(
You can crete FormData object and add as many values as you want inside it
var data = new FormData();
data.append("email", "eve.holt#reqres.in");
data.append("password", "pistol");
Then send this formData object to the post request
Like this
xhttp.send(data);

Javascript : Send JSON Object with Ajax?

Is this possible?
xmlHttp.send({
"test" : "1",
"test2" : "2",
});
Maybe with: a header with content type : application/json?:
xmlHttp.setRequestHeader('Content-Type', 'application/json')
Otherwise I can use:
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
and then JSON.stringify the JSON object and send it in a parameter, but it would be cool to send it in this way if it's possible.
With jQuery:
$.post("test.php", { json_string:JSON.stringify({name:"John", time:"2pm"}) });
Without jQuery:
var xmlhttp = new XMLHttpRequest(); // new HttpRequest instance
xmlhttp.open("POST", "/json-handler");
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify({name:"John Rambo", time:"2pm"}));
If you`re not using jQuery then please make sure:
var json_upload = "json_name=" + JSON.stringify({name:"John Rambo", time:"2pm"});
var xmlhttp = new XMLHttpRequest(); // new HttpRequest instance
xmlhttp.open("POST", "/file.php");
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(json_upload);
And for the php receiving end:
$_POST['json_name']
I struggled for a couple of days to find anything that would work for me as was passing multiple arrays of ids and returning a blob. Turns out if using .NET CORE I'm using 2.1, you need to use [FromBody] and as can only use once you need to create a viewmodel to hold the data.
Wrap up content like below,
var params = {
"IDs": IDs,
"ID2s": IDs2,
"id": 1
};
In my case I had already json'd the arrays and passed the result to the function
var IDs = JsonConvert.SerializeObject(Model.Select(s => s.ID).ToArray());
Then call the XMLHttpRequest POST and stringify the object
var ajax = new XMLHttpRequest();
ajax.open("POST", '#Url.Action("MyAction", "MyController")', true);
ajax.responseType = "blob";
ajax.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
ajax.onreadystatechange = function () {
if (this.readyState == 4) {
var blob = new Blob([this.response], { type: "application/octet-stream" });
saveAs(blob, "filename.zip");
}
};
ajax.send(JSON.stringify(params));
Then have a model like this
public class MyModel
{
public int[] IDs { get; set; }
public int[] ID2s { get; set; }
public int id { get; set; }
}
Then pass in Action like
public async Task<IActionResult> MyAction([FromBody] MyModel model)
Use this add-on if your returning a file
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
Adding Json.stringfy around the json that fixed the issue

Categories

Resources