ASP.NET JavaScript - Invalid JSON primitive - javascript

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!!

Related

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());
}

Correct content-type for sending this AJAX Post data

I am having problem sending base64 image data using ajax post
I think I have the wrong value for Content-Type but have tried application/json, text/json and image/jpeg without any success
Javascript
function sendFormData(fD)
{
var urls = fD.get('urls');
console.log('urls', urls);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/editsongs.update_artwork');
alert(urls);
xhr.setRequestHeader("Content-type", "image/jpeg");
xhr.send(urls);
}
Browser console shows
["data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUTExMWFhUXGRgbGBgXGR0aGRgXHRgYFx4YGxkYHiogGh4lGxgdIjEhJSkrLi4uGh8zODMtNygtLisBCgoKDg0OGhAQGy0lHSUtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIANEA8QMBIgACEQEDEQH/xAAcAAACAgMBAQAAAAAAAAAAAAAEBQMGAAECBwj/xABGEAACAQIEBAQDBAUJCAIDAAABAhEDIQAEEjEFIkFREzJhcQaBkRRCobEjUsHh8AcVM2JygsLR8RZDRFNzg5KyJDSzw8T/xAAZAQADAQEBAAAAAAAAAAAAAAABAgMABAX/xAAqEQACAgEDBQACAQQDAAAAAAAAAQIRAxIhMQQTFEFRImGRYnGh8AUjMv/aAAwDAQACEQMRAD8AsoosJt9cSpSdeYKYEXxKlQs4E2kEx6dMWJFBEDr0OPey5nCrR58MalwJUpB1nENbJWthpTyQDG5H5Y0gGqNQOJLLXA7h9K9VypGITSPbD+tSGIFy4mSJx0xz7EXjE7UscacNamW30jAlbLsNxiscqZNwoCK4wDEzJjkLiuoQjGNEYnCY5ZcawkMY5bEkY5GGsUijG1XtjcYPyFAQWMbbdsac9Ks0Y2wQphlwTKLUZg2wAwFmq8m5HYY5HFTRph0VnBI1QDZZgsZGwEnHPmn/ANb+lMcVqLFWRafKMTU+L6bRb88V/LcY+0otQKVmbdcbq1wsSYkgDfc7C3fHIoRlDVIs5tSpFzyXEtcdCdvlhopwp4RSpwvcAf64bj0x5mbSpUjrhdbmicSU1xi08djEWylGRjRGOsC5uodl379sBK2F8HbMAJxUON5lqrQFMA4f1CVU62ke2FaZlWqXgAbepx29MtD1VZzZXaol4RwYKsuAWP4…
Java Server code
public String updateArtwork(Request request, Response response)
{
System.out.println("Received artwork");
for(String s:request.queryParams())
{
System.out.println("---"+s);
}
System.out.println("ReadParms");
return "";
}
just outputs
Received artwork
ReadParms
Updated to Send as Form Instead
// Once we got everything, time to retrieve our objects
function sendData()
{
var fD = new FormData();
// send Files data directly
var files = imgList.filter(
function isFile(obj)
{
return obj.type === 'file';
}
);
files.forEach(
function appendToFD(obj)
{
fD.append('files[]', obj.file);
}
);
// for elems, we will need to grab the data from the server
var elems = imgList.filter(
function isElem(obj)
{
return obj.type === "element";
}
);
var urls = elems.map(
function grabURL(obj)
{
return obj.element.src;
}
);
if (urls.length)
fD.append('urls', JSON.stringify(urls));
sendFormData(fD);
};
function sendFormData(fD)
{
// but here we will just log the formData's content
var files = fD.getAll('files[]');
console.log('files: ', files);
var urls = fD.get('urls');
console.log('urls', urls);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/editsongs.update_artwork');
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(fD);
}
then on server I have
public String updateArtwork(Request request, Response response)
{
System.out.println("Received artwork");
for(String s:request.queryParams())
{
System.out.println("***"+s);
System.out.println(request.queryParams(s));
}
System.out.println("ReadParms");
return "";
}
and its outputs
Received artwork
***-----------------------------330219842643
Content-Disposition: form-data; name
"urls"
["data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMSEhUSExIWFhUXFxgXGBcYFRgXFxkdGBcWGBgYFx0YHSggHR0lHRkYITEhJSkrLi4uFyA1ODMtNygtLisBCgoKDg0OFQ8PFSsZFRkrLSstLSstKysrLS03KystLSstKy03LSstLSstNzc3KysrLS0tKysrKysrKysrKysrK//AABEIAKoBKQMBIgACEQEDEQH...."]
-----------------------------330219842643--
ReadParms
So I'm now getting the data but I don't understand really understand how to parse the Content-Disposition part in Java.
This code wasn't originally written by me, as you can see the FormData is constructed it doesnt come from an actual form. My first attempt was to try and extract from FormData and send in different way, an alternative would be to not store in FormData in the first place but dont know how to do this.
Update 2
Tried just sending first url rather than formdata or an arrya of urls, because actually there is only ever one url.But it just doesnt work, nothing received by server ?
function sendFormData(urls)
{
console.log('urls', urls[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/editsongs.update_artwork');
xhr.setRequestHeader("Content-type", "text/json");
alert(JSON.stringify(urls[0]));
xhr.send(JSON.stringify(urls[0]));
}
You are trying to view data in the body using queryParams(), which will give you the query params that are located in the url.
Load data from the request body using body().

How do i correctly format parameters passed server-side using javascript?

I cannot figure out how to get the following code working in my little demo ASP.NET application, and am hoping someone here can help.
Here is the javascript:
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = escape(theName);
var url = "Default.aspx/CheckName";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
//none of my attempts to set the 'values' parameter work
var values = //JSON.stringify({userName:"userName"}); //"{userName:'temp name'}"; //JSON.stringify({ "userName":userName });
request.send(values);
}
}
Here is the method in my *.aspx.cs class:
[WebMethod]
[ScriptMethod(UseHttpGet=true)]
public static string CheckName(string userName)
{
string s = "userName";
return s + " modified backstage";
}
When this code runs I receive this exception:
---------------------------
Message from webpage
---------------------------
{"Message":"Invalid web service call, missing value for parameter: \u0027userName\u0027.","StackTrace":" at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
---------------------------
OK
---------------------------
I started searching here, then went on to several threads on SO, trying quite a few combinations of quotation marks and key-value pairs, but nothing I've tried has worked.
When I remove the parameter from the C# method and request.send(), I get a response in my JS callback that I can work with. But as soon as I try to do something with parameters, I get the above exception. I'd like to know how to do this without using jQuery, if possible.
Thanks in advance.
FINAL VERSION
Using Alexei's advice, I ended up with the following, which works. The URL was missing the apostrophes on either end of the parameter value; this was keeping the call from going through.
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = encodeURIComponent(theName);
var url = "Default.aspx/CheckName?name='" + theName + "'";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.send();
}
}
request.send(values);
This won't work with a "GET". Try
request.open("POST", url, true);
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp
You need to:
decide whether you want GET or POST. For GET request you need all parameters to be in Url (and body to be empty), for POST you can use both. As of current code you are expecting GET, but sending POST.
properly add query parameter - name and encoded value. encodeUriComponent is JavaScript function of choice, see Build URL from Form Fields with Javascript or jquery for details
if using POST you need to properly encode parameters there too as well specify correct "content-type" header.
if sending JSON you need to decode JSON server side.
Alternatively you can use hidden form to perform POST/GET as covered in JavaScript post request like a form submit
Side note: jQuery.ajax does most of that for you and good source to look through if you want to do all yourself.
Like Alan said, use the POST method. Or pass your arguments in your URL before opening it, e.g.
var url = "Default.aspx/CheckName?userName=" + values;
EDIT : no, it's probably a bad idea since you want to send JSON, forget what I said.
If you need to go for POST, then you need to send it like this.
var values = JSON.stringify({"'userName':'"+ userName+ "'"});
And you have to change HttpGet to HttpPost
Given that your server side method asks for GET, you need:
request.open("GET", url + "?username=" + userName, true);
request.send();
The works for me:
function checkUserName() {
var request = new XMLHttpRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var userName = "Shaun Luttin";
var url = '#Url.RouteUrl(new{ action="CheckName", controller="Home"})';
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE ) {
if(request.status == 200){
document.getElementById("myDiv").innerHTML = request.responseText;
}
else if(request.status == 400) {
alert('There was an error 400')
}
else {
alert('something else other than 200 was returned')
}
}
}
request.open("GET", url + "?username=" + userName, true);
request.send();
}
}
With this on the server side:
[HttpGet]
public string CheckName(string userName)
{
return userName + " modified backstage";
}

pass array in javascript .send function

This is regarding passing an array to a php page.Is it possible to send an array like this(code below)? if its not possible , what changes should i bring about to my code?
function ajax_post(){
var hr = new XMLHttpRequest();
hr.open("POST", "get_numbers.php", true);
hr.setRequestHeader("Content-type", "application/json");
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var data = JSON.parse(hr.responseText);
var results=document.getElementById("ace");
//results.innerHTML=data.u1.port;
for (var obj in data)
{
results.innerHTML+=data[obj].port;
}
}
}
var cards= new Array();
cards[0]="hearts";
cards[1]="spades";
hr.send(cards);
results.innerHTML = "processing...";
}
.send() doesn't take a javascript array. There are a number of forms of data you could send and you will have to decide which form is appropriate, but an array is not one of them. The simplest would be to turn the array into a JSON string and send that.
var cards = [
"hearts",
"spades"
];
hr.send(JSON.stringify(cards));
Then, on the receiving end of things, you would parse the JSON back into whatever language form you are using on the server end. If it's PHP, then you can use the PHP functions for parsing the JSON which will put the data into a PHP array on your server.
Per the MDN doc page for the XMLHttpRequest object, .send() can take the following types of data:
void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);
Using JSON would be using the string type.

Force "charset=x-user-defined'" on jQuery Ajax Post

I am trying to call a Hessian web service from a Javascript application, but I'm having issues parsing the response, since jQuery is treating the response as text and stripping the first bytes of it.
In my research, I have found out that you need to set the charset as 'charset=x-user-defined' in order to the browser leave my bytes as is. But, according the ajax docs:
Sending Data to the Server
By default, Ajax requests are sent using the GET HTTP method. If the
POST method is required, the method can be specified by setting a
value for the type option. This option affects how the contents of the
data option are sent to the server. POST data will always be
transmitted to the server using UTF-8 charset, per the W3C
XMLHTTPRequest standard.
And indeed, the charset is not changing regardless of the settings I used. I have tried the following, separately and all at once, with no luck
$.ajax({
type : 'POST',
url : url,
timeout : 3000,
data : parameters,
contentType : "x-application/hessian; charset=x-user-defined'",
mimeType: 'text/plain; charset=x-user-defined',
headers: {
Accept : "text/plain; charset=x-user-defined",
"Content-Type": "text/plain; charset=x-user-defined"
},
beforeSend : function(xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
})
Also I tried to mess around with the data converters and custom contenttypes defined in jQuery, with no succes.
It appears that as per the standard, I will not be able to do this. It works with GET but not with POST, and the Hessian protocol requires POST.
Do you have any ideas? Or do I need to start to build my XHR method form scratch?
Turns out that I was making a silly mistake somewhere else. But anyhow, I found a sweet way for handling binary data on request and responses, from here.
define(function() {
// Do setup work here
function configurationException(message) {
throw new Error(message + " missing from configuration object");
}
return {
post : function(config) {
if (config) {
var url = config.url || configurationException("url");
var done = config.done || configurationException("callback function");
var timeout = config.timeout || 10000;
var data;
if (config.data) {
data = config.data;
} else {
data = null;
console.warn('No data is specified in binaryPost');
}
var request = new XMLHttpRequest();
request.open("POST", url, true);
request.responseType = "arraybuffer";
request.setRequestHeader("Content-Type", "x-application/hessian;");
request.onload = function(oEvent) {
var arrayBuffer = request.response; // Note: not oReq.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
done(byteArray);
}
};
request.send(data);
} else {
throw new Error("Configuration object is missing");
}
}
};
});
Hope you find it useful

Categories

Resources