JSON output from web method - ajax

I have a web method returning JSON to a fullCalendar as event data but a "()" is added to it causing a parser error.
I am able to clip off the unwanted "()" and then attach the events with jQuery but obviously don't want to keep it this way.
The source of the data is a web method using Razor. Using the JSON helper to encode the data results in a well formed JSON string, i.e. no "()". Of course if I use encode I then would use Response.Write to send the data back to the AJAX function. The same ill formed JSON data is recieved if I use JSON.Write(data, Response.Output).
Catching the returned data in the success function shows the data with the attached "()".
Here is a portion of the web method that returns the data:
// convert the header names and data to strings
var rows = from e in cE
select new
{
id = e.EvId,
title = e.Title,
start = e.startT,
allDay = false,
end = e.endT,
backgroundColor = e.eventColor
};
string mJson = Json.Encode(rows);
//Json.Write(rows, Response.Output);
Response.Write(mJson.Trim());
here is the result of the encode:
"[{\"id\":9,\"title\":\"new event\",\"start\":\"2012-05-29 19:00:00\",\"allDay\":false,\"end\":\"2012-05-29 20:00:00\",\"backgroundColor\":\"Orange \"},{\"id\":9,\"title\":\"new event\",\"start\":\"2012-06-05 19:00:00\",\"allDay\":false,\"end\":\"2012-06-05 20:00:00\",\"backgroundColor\":\"Orange \"},{\"id\":9,\"title\":\"new event\",\"start\":\"2012-06-12 19:00:00\",\"allDay\":false,\"end\":\"2012-06-12 20:00:00\",\"backgroundColor\":\"Orange \"},{\"id\":10,\"title\":\"another\",\"start\":\"2012-06-22 19:00:00\",\"allDay\":false,\"end\":\"2012-06-22 19:45:00\",\"backgroundColor\":\"Orange \"},{\"id\":10,\"title\":\"another\",\"start\":\"2012-06-29 19:00:00\",\"allDay\":false,\"end\":\"2012-06-29 19:45:00\",\"backgroundColor\":\"Orange \"}]" string
Here is what the AJAX success function shows as the recieved data:
"[{"id":9,"title":"new event","start":"2012-05-29 19:00:00","allDay":false,"end":"2012-05-29 20:00:00","backgroundColor":"Orange "},{"id":9,"title":"new event","start":"2012-06-05 19:00:00","allDay":false,"end":"2012-06-05 20:00:00","backgroundColor":"Orange "},{"id":9,"title":"new event","start":"2012-06-12 19:00:00","allDay":false,"end":"2012-06-12 20:00:00","backgroundColor":"Orange "},{"id":10,"title":"another","start":"2012-06-22 19:00:00","allDay":false,"end":"2012-06-22 19:45:00","backgroundColor":"Orange "},{"id":10,"title":"another","start":"2012-06-29 19:00:00","allDay":false,"end":"2012-06-29 19:45:00","backgroundColor":"Orange "}]();???"

Related

Unable to view PDF attached with ServiceNow table records

I am able to successfully attach PDF file with ServiceNow table record using GlideSysAttachment API and attachment.write() function in script, however whenever I download and try to open same, I get the error shown in below screenshot.
Code snippet
(function execute() {
try{
var rec = new GlideRecord('incident');
var attachment = new GlideSysAttachment();
var incidentSysID = incident.number;
rec.get(incidentSysID);
var fileName = 'Test_Incident.pdf';
var contentType = 'application/pdf'; // Also tried with contentType as 'text/pdf'
var content = pdf_content;
var agr = attachment.write(rec, fileName, contentType, content);<br>
gs.info('The PDF attachment sys_id is: ' + agr);
}catch(err){
gs.log('Got Error: ' + err);
gs.info(err);
}
})()
I also tried "AttachmentCreator" with ecc_queue within script but same error occurs. Below is code for it.
(function execute()
{var attCreator = new GlideRecord('ecc_queue');
attCreator.agent = "AttachmentCreator";
attCreator.topic = "AttachmentCreator";
attCreator.name = "Test.pdf" + ":" + "text/pdf";
//Also tried, "Test.pdf:application/pdf"
attCreator.source = "incident"+":"+ incident.number;
// Record Table name and sys_id of the particular record
var content = pdf_content; // pdf_content is any string variable
var stringUtil = new GlideStringUtil();
var base64String = stringUtil.base64Encode(content);
var isValid=GlideStringUtil.isBase64(base64String);
var base64String= gs.base64Encode(content);
gs.info("Is valid base64 format in ecc_queue ? "+ isValid);
attCreator.payload = base64String; //base64 content of the file
attCreator.insert();
})()
I am able to attach and view excel and word files with similar scripts without any issues. I have checked system properties for attachments but everything looks fine. I am able to view the PDF file uploaded from UI to particular table records however not the one I attach via REST API or scripts.
I have also tried sending encoded data as bytes, base64 or simple string but nothing seems to work. I don't get any errors and attachment id is returned each time on creation of attachment.
After modifying my code slightly for above functions w.r.t scoped application instead of global; I got some information from logs when I debug:
05:38:38.411 Security restricted: File type is not allowed or does not match the content for file Test.pdf
05:38:38.410 Security restricted: MIME type mismatch for file: Test.pdf. Expected type:application/pdf, Actual type: text/plain
05:38:38.394 App:XYZ App x_272539_xyz_ap: Is valid base64 format in ecc_queue ? true
First a comment: This line in your code is accidentally working -- make sure you understand that a task number is not the object sys_id
var incidentSysID = incident.number; // should be incident.sys_id
Next, it's unclear where the PDF content is coming from. IF your complete code is listed, I would expect the errors given as you have noted that pdf_content is "any string variable."
ServiceNow does have a the capability to create a PDF from an HTML argument.
Generating a PDF from HTML
Here's a helpful blog post for getting a PDF (Platform generated) of an existing record:
Love PDF? PDF loves you too

How to include json as a query parameter in Zapier app

I am trying to create a Zapier app to create a new invoice in Zoho.
Has the requirements: Content-Type: application: x-www-form-urlencoded and input JSON string should be passed using JSONString parameter
The following URI is working for me in REST console when I set the Content Type to "application/x-www-form-urlencoded" and method POST.
https://invoice.zoho.com/api/v3/invoices?authtoken=xxxxxx&organization_id=xxxxxx&JSONString={"customer_id":"xxxxxx","line_items":[{"item_id":"xxxxxx"}]}
However my problem is trying to implement this into Zapier. I think I need to use a function like below to convert the JSON into the right format, but I have no idea how to turn this into a query paramater called JSONString.
create_invoice_pre_write: function(bundle) {
var data = JSON.parse(bundle.request.data);
bundle.request.data = $.param(data);
bundle.request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
return bundle.request;
}
Just need a point in the right direction. I'm not sure what to try next.
You can create an Invoice in Zoho Invoice through Zapier using the below snippet of code.
You can set the query params in bundle.request.params which you want to send it to ZI for the creation of Invoice.
create_invoice_pre_write: function(bundle)
{
var data = JSON.parse(bundle.request.data);
bundle.request.method = "POST",
bundle.request.url = "https://invoice.zoho.com/api/v3/invoices",
bundle.request.params.authtoken = {authtoken},
bundle.request.params.organization_id = {organization_id},
bundle.request.params.JSONString = data
bundle.request.headers= "'Content-Type':'application/x-www-form-urlencoded'";
return bundle.request;
}
This should be working for you. If you have any doubts do let me know.

Compression response filter fails on breeze.js Metadata call

I have an http module where I'm adding a response filter below for compression. This works for all API calls except for 1, the call to MetaData. If I remove the [BreezeController] decoration it works fine. I think it has to do with action filter attribute that converts the string return type into an HttpResponse return type with string content.
The error I'm getting is " Exception message: The stream state of the underlying compression routine is inconsistent."
I've done some testing where a method thats defined to return an HttpResponse works fine. So I think its the scenario where the method is defined to return string, and then the action filter changes it to HttpResponse at runtime.
Any ideas how I can get this to work?
Here's the response filter being added in BeginRequest:
HttpApplication app = (HttpApplication)sender;
// Check the header to see if it can accept compressed output
string encodings = app.Request.Headers.Get("Accept-Encoding");
if (encodings == null)
return;
Stream s = app.Response.Filter;
encodings = encodings.ToLower();
if (encodings.Contains("gzip"))
{
app.Response.Filter = new GZipStream(s, CompressionMode.Compress);
app.Response.AppendHeader("Content-Encoding", "gzip");
}
Don't know the specifics of what you're doing but I know that the [BreezeController] attribute strips out filters and adds back just the ones that breeze wants.
One approach might be to define a separate controller (ModelMetadataController) that only serves the metadata. This controller doesn't have the [BreezeController] attribute; it's a plain old Web API controller.
Then you create a "Breeze controller" (ModelController) with all of the usual methods except the Metadata method.
You call the metadata controller from the client during app launch via MetadataStore.fetchMetadata just to get metadata.
Once you have populated a metadataStore in this fashion, you use it in your EntityManager which sends query and save requests to the "real" Web API data controller.
The client code might look something like this:
var ds = new breeze.DataService({
serviceName: 'breeze/Model' // the breeze query & save controller
});
var ms = new MetadataStore({
namingConvention: breeze.NamingConvention.camelCase, // assuming that's what you want
});
ms.addDataService(ds); // associate the metadata-to-come with the "real" dataService
var manager = new breeze.EntityManager({
dataService: ds,
metadataStore: ms
});
// the fun bit: fetch the metadata from a different controller
var promise = ms.fetchMetadata('breeze/ModelMetadata') // the metadata-only controller!
return promise; // wait on it appropriately

How to load image list from REST API using angularJS

I have searched in this forum for quiet a bit and here's my problem -
I have a ng-repeat in my html which takes in a list of messages(Json object).
Each message JSON has a sender email address - e.g. abc#gmail.com
Now, I have to get the email address from the message and form another REST API request to fetch their images for e.g. - http://<>:8080/getImage/abc#gmail.com (email address dynamic)
So in my code, I'll have a ng-repeat and a ng-src pointing to the image REST URL
If there's no image in server, it returns a 404 and displays a broken image on the UI. How do I handle it? On the other hand, if I make a http request to determine if there's a success message and on failure return a default image, then the whole thing goes through an endless loop. I'll try to create a fiddle and include it for better explanation.
Use the error block to handle such behavior:
function($http) {
var restUrl = 'getImage/abc';
return {
fetchImage: function(imageId) {
var self = this;
return $http.get(restUrl + '/' + imageId).
success(function(data) {
return self.imageUrl = data;
}).
error(function(data) {
return self.imageUrl = "pathToDefaultImage";
});
},
...

json/ajax confusion

I've got a response that sends back an entire table. N number of rows with 7 cells in each row. So I end up with nX7 responses. Apparently, I should be using JSON to handle the string appropriately. I've found tutorials on how to create a JSON object, but not so much on how to send it via ajax and how in sending it through ajax, the jsp knows to fill the JSON object with the responses... In other words,
I create JSON object in javascript (check)
place JSON object in the ajax code (confused)
response with JSON object filled (confused)
Parse JSON object so I can get at the data easily (maybe confused, we'll see after steps 2/3)
I am not using jquery as I'm still learning and jquery's syntax is confusing currently.
var sweekStart = document.getElementById("weekStart").value;
var smonth = document.getElementById("month").value;
var syear = document.getElementById("year").value;
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "empTableRepop.jsp?weekStart=" + encodeURIComponent(sweekStart)+"&month="+encodeURIComponent(smonth)+"&year="+encodeURIComponent(syear);
xmlhttp.open("POST",url,true);
//alert("made it to open");
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
//alert(xmlhttp.responseText);
var test = xmlhttp.responseText;
reFillTable(test);
}
}
xmlhttp.send(null);
The variable "test" (yea, bad name but it's temporary) is the object I want converted from a standard var to a JSONobject. If I understand correctly, JSON will already have the string parsed when it receives the response. I realise I can change "function()" to be directly "reFillTable(test)" but given the path it took me to get it working I ended up with that somehow lol. Will fix once everything is working properly.
EDIT:
This is how I "display" the information from the jsp/java file.
//Name Cell
out.println(empName);
//Mondays Hours
out.println(hoursArr[0]);
//Tuesdays Hours
out.println(hoursArr[1]);
//Wednesdays Hours
out.println(hoursArr[2]);
//Thursdays Hours
out.println(hoursArr[3]);
//Fridays Hours
out.println(hoursArr[4]);
//Total hours Cell
out.println(PTOAmt);
Assuming that your serverresponse is already working, this gives you the JavaScript object from the received JSON.
var test = JSON.parse( xmlhttp.responseText );
To clarify: There is no explicit "JSONObject" in JavaScript. JSON stands for JavaScript Object Notation and is simply a shorthand for writing normal JavaScript objects. It became, however, popular as a means of serializing data to send through AJAX-request.
In the end the server just sends a string in JSON format, which you on the other hand have to parse again (by JSON.parse()) in order to have an object representing the data send.
Just to add: JSON.stringify() is the operation in the other direction. Creating a string out of a JavaScript object.
With respect to the edit:
As said in the comment, this does not create valid JSON (have a look # json.org for an overview).
So now you have some choices:
Use a library like GSON to encode your data.
Parse your data by hand in JavaScript. (I would not recommend this).
Create a valid JSON string manually.
The code for the third option, may look like this:
// start the JSON object
out.print( "{" );
//Name Cell
out.println( "\"empName\":\"" + empName + "\"," );
// start an array for the next few values
out.print( "\"hours\": [" );
out.print(hoursArr[0] + "," );
out.print(hoursArr[1] + "," );
out.print(hoursArr[2] + "," );
out.print(hoursArr[3] + "," );
out.print(hoursArr[4] + "," );
// end the array
out.print( "]," );
//Total hours Cell
out.print( "\"PTOAmt\":\"" + PTOAmt + "\"");
// end the JSON
out.print( "}" );
This assumes that PTOAmt is a string as well.
On the long run you should use a library like mentioned in option (1) to handle the encoding.

Resources