jQuery ajax callback receiving incorrect json result - json

In my asp.net mvc 4 web app my action in the controller seems to return a invalid data to the jquery ajax callback... The action is doing a ping to an IP and it is called several times from several ajax calls in order to do pings to several IPs.
A piece of my action in the controller (below what is returned):
Response.ContentType = "application/json;charset=utf-8";
Response.StatusCode = (int)(packetsLost < 4 ? HttpStatusCode.OK : HttpStatusCode.NotFound);
Response.TrySkipIisCustomErrors = true;
return new JsonResult()
{
ContentType = "application/json;charset=utf-8",
Data = new
{
sent = 4,
received = 4 - packetsLost,
lost = packetsLost,
percentLost = (int) (packetsLost / 4 * 100),
responseStatus01 = statuses[0],
responseStatus02 = statuses[1],
responseStatus03 = statuses[2],
responseStatus04 = statuses[3],
responseMessage01 = responseStatuses[0],
responseMessage02 = responseStatuses[1],
responseMessage03 = responseStatuses[2],
responseMessage04 = responseStatuses[3],
rtt01 = rtt[0],
rtt02 = rtt[1],
rtt03 = rtt[2],
rtt04 = rtt[3],
ttl01 = ttl[0],
ttl02 = ttl[1],
ttl03 = ttl[2],
ttl04 = ttl[3],
minRtt = roundTripTimes.Count == 0 ? "0" : string.Format("{0}ms", roundTripTimes.Min()),
maxRtt = roundTripTimes.Count == 0 ? "0" : string.Format("{0}ms", roundTripTimes.Max()),
avgRtt = roundTripTimes.Count == 0 ? "0" : string.Format("{0}ms", roundTripTimes.Average())
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
and jquery ajax call:
ajax({
url: '/Controller/Action/',
type: 'POST'
}).then(function (data) {
var _data;
try {
_data = $.parseJSON(data);
}
catch (err) {
alert("Something went bad!!!");
}
}, function (data) {
var _data;
try {
_var = $.parseJSON(data.responseText);
}
catch (err) {
alert("Something went bad!!!");
}
});
1) When action returns http status code OK (200) data.responseText in the jquery ajax callback is empty so I convert data instead (that contains correct data) but for some reason it is crashing when converting using parseJSON(data): error catched says invalid character... I do not know why...
2) When action return http status code NotFound (404) data.responseText sometimes (not always) is empty and statusText within data is "error" so neither I do not understand it....
Action in the controller always is returning the correct data....
Could someone help me to detect this error? or right me in the right direction....
UPDATED:
From ie dev tools, in network, I have observed that some pings are cancelled and then when trying to process them it returns empty responseText to the ajax callback so when trying to parse it, it crashes. I have observed that If I set the timeout for ping to a lower value, for example, 750ms, it is working but if i use the default timeout for ping, that is, 5sec, then it does not work: some pings are cancelled and when trying to serve them they are returning empty responseText that cause it to crash when trying to parse in ajax callback.

Related

Forge Model Derivatives: GET metadata always returns 202

I'm trying to get the Derivative Tree Json view of a large file in nwd format, but it always responds with the status code 202:
{"result":"success"}
My objective is to get the dbids of the first level of the tree with its name. If this works, it would be to get their properties via {urn}/metadata/{modelGuid}/properties
RestClient client = new RestClient("https://developer.api.autodesk.com");
RestRequest request = new RestRequest("/modelderivative/v2/designdata/{urn}/metadata/{modelGuid}", Method.Get);
request.AddHeader("Authorization", "Bearer " + authenticate.access_token);
//request.AddHeader("x-ads-force", true);
request.AddHeader("Content-Type", "application/json");
request.AddParameter("urn", urn, ParameterType.UrlSegment);
request.AddParameter("modelGuid", guid, ParameterType.UrlSegment);
request.AddParameter("forceget", true, ParameterType.QueryString);
request.AddParameter("objectid", 1, ParameterType.QueryString);
request.AddParameter("level", 1, ParameterType.QueryString);
var response = await client.ExecuteAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
{
var result = response.Content;
}
Who can help?
Thanks
According to the documentation Fetch Object Tree, the status code 202 means : "Request accepted but processing not complete. Call this endpoint iteratively until a 200 is returned."
It seems pretty normal if you are working with a large model. But you should be able to get the 200 response after waiting some time.
Appending what Alex said, you can use do-while to check if the response code is 200.
ApiResponse<dynamic> treeRes = null;
do
{
treeRes = await // Your API reqeust here
if (treeRes == null) throw new InvalidOperationException('Failed to get tree');
if (treeRes.StatusCode != 200)
System.Threading.Thread.Sleep(60 * 1000);
}
while (treeRes.StatusCode != 200);
var properties = treeRes.Data;

Why is the observable sending old values

I have created a service which sends a request to the backend and makes the result available to the component via an observable.
export class QuestionManagementService {
questionsArray$: Observable<Result>;
private questionsArraySubject: BehaviorSubject<Result>; //to send list of questions
...
constructor(private http: HttpClient, private helper:HelperService, private bs:WebToBackendInterfaceService, private loaderService:LoaderService) {
this.questionsArraySubject = new BehaviorSubject<Result>(new Result('initial',{})); //A Subject can act both as an Observable and an Observer
this.questionsArray$ = this.questionsArraySubject.asObservable(); //create Observable. Other components can subcribe to it now to get notifications/values
...
}
//this method sends the request to network via another `bs` service. The request is sent using `http.post`
getQuestions(questionFilter:GetQuestionsfilter){
console.log("In QuestionManagementService: getQuestions");
let observable:Observable<HttpEvent<any>> = this.bs.getQuestions(questionFilter);
let subscription:Subscription = observable.subscribe((ev:HttpEvent<any>)=>{
if(ev.type === HttpEventType.Response) { //null means that the response wasn't an HttpResponse but probably some internal Rxjs event (eg type 0)
let response= <HttpResponse<any>>ev;
console.log("http response received: ",response);
//should remove the token from storage
console.log('response body from server: ',ev.body);
let isResponseStructureOK: boolean = this.helper.validateServerResponseStructure(ev.body);
if (isResponseStructureOK) {
console.log("response structure is OK");
let response: ServerResponseAPI = ev.body;
let result:string = response.result;
console.log("result is : " + result);
/*if result could be success or error*/
/*additionalInformation is a string and the string contains a valid json which has array of questions
in format {"questions-list":[{"tag":"some tag1","description":"some description1"},{{"tag":"some tag2","description":"some description2"},...]}
*/
let message:string = response['additional-info'];
console.log("message is "+message);
if(result === "success") {
let jsonQuestionList: string = response['additional-info'];
console.log("jsonQuestionList response as string: ", jsonQuestionList);
//let jsonQuestions: PracticeQuestionsListAPI = JSON.parse(jsonQuestionList);
//console.log("jsonQuestion array:", jsonQuestions);
//this.questionsArraySubject.next(jsonQuestions['questions-list']);
this.questionsArraySubject.next(new Result('success', response["additional-info"]));
} else {
this.questionsArraySubject.next(new Result('error', response["additional-info"]));
}
}
else {
/**
* If something goes wrong, send error rather than send next with result="error"
*/
console.log("received incorrect response structure from server: ", ev.body);
//TODOM - need to change hard coded responses and pick them from a config or global variable.
this.questionsArraySubject.error(new Result('error',"Invalid response structure from server"));
}
}
else {
console.log("not response. ignoring");
}
},
(error:ServerResponseAPI)=>{/*web to backend service will send error in ServerResponseAPI format. This is what handleError throws*/
console.log("got error from the Observable: ",error);
this.questionsArraySubject.error(new Result('error',error['additional-info']));
},
()=>{ //observable complete
console.log("observable completed")
});
}
}
The following component subscribes to this service.
export class PraticeQuestionListComponent implements OnInit, OnDestroy {
questions: PracticeQuestionsListAPI; //the result from observable will be stored here.
questionListSubscription:Subscription; //reference of the subscription
ngOnDestroy(): void {
console.log("destroying component. unsubscribing");
this.questionListSubscription.unsubscribe()
}
//on initialisation, I subscribe to the observable
ngOnInit(){
console.log("in question list on init. question is ",this.questions);
...
this.questions= new PracticeQuestionsListAPI(new AdditionalPagingInfo("",new PartitionInfo(0,0)),
[]);
let tagSubscription = this.questionManagementService.getSupportedTags(new TagId("coding"));
console.log("subscribing to question mgmt service");
this.questionListSubscription = this.questionManagementService.questionsArray$.subscribe((result:Result)=>{
console.log('received result from question mgmgt service - array observable',result);
if(result.result === "success") { //received response from server
let questionList = JSON.parse(result.additionalInfo) as PracticeQuestionsListAPI;
console.log("got list of questions value ", questionList);
this.questions['pagination-info'] = questionList['pagination-info'];
this.questions['questions-list'] = questionList['questions-list'];
/*
0 length of questions-list means no questions.
this could be response from the server indicating that there are no more questions
*/
/*
* the server indicates that there are no more questions by either sending empty question list or by sending
* 0 values for pagination state and partition info
*/
if (questionList["questions-list"].length !== 0) { //server has send list of questions
this.questions['pagination-info']['page-state'] = questionList['pagination-info']['page-state'];
this.questions['pagination-info']['partition-info'] = questionList['pagination-info']['partition-info'];
this.questions['questions-list'] = questionList['questions-list'];
console.log("previous question filter is ",this.questionsFilter);
this.questionsFilter["pagination-info"]["page-state"]=questionList["pagination-info"]["page-state"];
this.questionsFilter["pagination-info"]["partition-info"].month=questionList["pagination-info"]["partition-info"].month;
this.questionsFilter["pagination-info"]["partition-info"].year=questionList["pagination-info"]["partition-info"].year;
console.log("new question filter is ",this.questionsFilter);
//TODOM - maybe this assignment below was causing memory leak. So changed this as above
//this.questionsFilter['pagination-info'] = questionList['pagination-info'];
this.lastPage = false; //the server indicates that there are no more questions by sending these values (no paging state and no partition info)
if (this.questions['pagination-info']['page-state'].length == 0 &&
this.questions['pagination-info']['partition-info'].year == 0 &&
this.questions['pagination-info']['partition-info'].month == 0) {
this.lastPage = true;
} else {//if the list is empty then there are no (more) questions for the selected tag
this.lastPage = false;
}
} else {
this.lastPage = true; //Don't show next button if there are no questions.
this.showDialog(new PracticeQuestionListContext("Reached end of the search. No more results available", new PracticeQuestionListAdditionalInfo()));
}
} else {
//TODOM - I should probably display the error in case there is an error from the server
console.log("ignoring value");
}
},
(err:Result)=>{
console.log("received error from QuestionArray observable",err);
//TODOM - probably should change the name of DialogContext to Component specific additional context
this.showDialog(new PracticeQuestionListContext(err.additionalInfo,new PracticeQuestionListAdditionalInfo()));
},
()=>{
console.log("question mgmt service, questionarray observable completed.");
});
}
}
The issue I am facing is that if I visit the component for the first time, I get the values from the observable after making some selections in the UI (expected behavior). Then i visit the home page of the application, the component gets destroyed (again, expected behavior). Then if I visit the component again, the observable sends the old values (from the first visit) even when I have not made any UI selections.
Why is the observable sending old values and how can I stop it from doing that? I have created another question in SO with pictures which might explain the scenario better
angular component is retaining old value maybe because the observable is resending past data

NodeJS request not giving any response in AWS Lambda

I am using NodeJS request module to pass a JSON request to a URL and generate a JSON response from it. I tried this code and it generates a valid response. I am pasting the link for a StackOverflow question I asked for the same.
NodeJS Request returning an empty array inside a JSON response
However, when I utilize the same logic in AWS Lambda, there is no response at all from the module. Since there is no response at all, I cannot understand what the problem is.
This is the handling function for the AWS Lambda with Alexa as a trigger.
'use strict';
var request = require('request');
var accountNumberRequest = {};
var balanceResponse = {};
const url = "https://ibluatapig.indusind.com/app/uat/balinq/AccountEnquiry?client_id=6867b781-9b21-45c5-9c55-948f7cd1a33f&client_secret=hP3yB3hM2oH4pH4hM1kV3uY8vR3qV7jY8cF6bG2sF5jX8lT1vN";
var bal = {};
exports.handler = function (event,context) {
try{
console.log("Try Started");
var req = event.request;
console.log("Request Generated");
if(req.type === "LaunchRequest") {
console.log("Launch Request! Calling handleLaunchRequest");
handleLaunchRequest(context);
} else if(req.type === "IntentRequest") {
console.log("IntentRequest");
let options = {};
console.log(0);
if(req.intent.name === "BalanceIntent") {
console.log("Balance Intent");
//Got the account number from Alexa request
let accNo = req.intent.slots.AccountNumber.value;
console.log(accNo);
accountNumberRequest = {
"AERequest":{
"serviceType":"BE",
"deviceId":"Test",
"accountId":accNo
}
};
console.log(accountNumberRequest);
console.log("Calling NodeJS.Request");
request({
url: url,
method: "POST",
json: true,
header: {
"content-type": "application/json",
},
body: accountNumberRequest
},
function(error, response,body){
if(!error && response.statusCode === 200){
console.log(body.AEResponse.AcctBal[1].BalAmt);
} else {
//options.speechText = `The account <say-as interepret-as = "digits">${accNo}</say-as> does not exist`;
console.log("error: "+error);
console.log("response.statusCode"+response.statusCode);
console.log("response.statusText"+response.statusText);
}
}
);
console.log("Balance Response should be assigned by now");
console.log(bal);
/* if(accountNumbers.hasOwnProperty(accNo)) {
var balance = accountNumbers[accNo];
accountExists = true;
}
if(accountExists == true){
options.speechText = `The balance of account number <say-as interpret-as = "digits">${accNo}</say-as> is <say-as interpret-as = "cardinal">${balance}</say-as>`;
} else {
options.speechText = `The account <say-as interepret-as = "digits">${accNo}</say-as> does not exist`;
}*/
context.succeed(buildResponse(options));
}
} else if(req.type === "SessionEndedRequest") {
//Code here
} else {
throw("Unknown Intent Type");
}
} catch(e){
context.fail("Exception "+e);
}
};
function getBalance(){
//Code to parse the JSON response and extract values from the response.
}
function handleLaunchRequest(context){
//Code for handling launch requests }
function buildResponse(options){
//Code for generating response
}
This is the problem...
// You're sending an asynchronous HTTP request here.
request();
// But you sent the response here without waiting for the above request to finish.
context.succeed();
Basically, you're executing context.succeed() before request() finishes. So you're basically ending your Lambda invocation without the response from that HTTP request.
To fix your code, put the context.succeed() inside the callback that you pass to the request() call.
P.S.
You should be using callback instead of the deprecated context.succeed()/context.fail() API.

Parsing JSON object sent through AJAX in Django

This is my code creating a json file:
$( ".save" ).on("click", function(){
var items=[];
$("tr.data").each(function() {
var item = {
itemCode : $(this).find('td:nth-child(1) span').html(),
itemQuantity : $(this).find('td:nth-child(4) span').html()
};
items.push(item);
});
});
Now the json object looks like:
[{"itemcode":"code1","itemquantity":"quantity1"},{"itemcode":"code2","itemquantity":"quantity2"},...]
My question is how do I parse this data in Django view?
Following is my AJAX function for reference:
(function() {
$.ajax({
url : "",
type: "POST",
data:{ bill_details: JSON.stringify(items),
calltype:'save'},
dataType: "application/json", // datatype being sent
success : function(jsondata) {
//do something
},
error : function() {
//do something
}
});
}());
Since I'm sending multiple AJAX request to the same view, I need the 'calltype' data as well.
Thanks you on your answer!! BTW, I badly need to know this simple stuff, which I'm missing
This is my code snippet for parsing:
if (calltype == 'save'):
response_data = {}
bill_data = json.loads(request.POST.get('bill_details'))
itemcode1=bill_details[0]['itemCode']
#this part is just for checking
response_data['name'] = itemcode1
jsondata = json.dumps(response_data)
return HttpResponse(jsondata)
The error being raised is
string indices must be integers
Request your help
For your reference, this is my POST response (taken from traceback):
bill_details = '[{"itemCode":"sav","itemQuantity":"4"}]'
calltype = 'save'
csrfmiddlewaretoken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
EDITED Django View
This is my edited view:
if (calltype == 'save'):
bill_detail = request.POST.get('bill_details')
response_data = {}
bill_data = json.loads(bill_detail)
itemcode1=bill_data[0]['itemCode']
#this part is just for checking
response_data['name'] = itemcode1
jsondata = json.dumps(response_data)
return HttpResponse(jsondata)
I fail to understand the problem. SO, to solve it, my question: what is the datatype of the return for get call and what should be the input datatype for json.loads. Bcoz the error being shown is json.loads file has to be string type!! (Seriously in limbo)
Error:
the JSON object must be str, not 'NoneType'

How to parse a JSONP response and return a value using OpenLayers?

I am using OpenLayers and geoserver to build an app. very new to everything and this is my first app. Now I am trying to use the WMS getFeatureInfo to fetch feature information and show in popups when users click on a feature. To get around the cross domain issue, I am now trying to get JSONP response. the response i got is:
parseResponse({"type":"FeatureCollection","features":[{"type":"Feature","id":"Fire_Boundary_Pro.1","geometry":{"type":"MultiPolygon","coordinates":[[[[414495.86280000024,6451439.778],[414501.3269999996,6451437.0124],[414572.5887000002,6451444.5907],[414614.8359000003,6451368.1611],[414679.86149999965,6451410.5882],[414793.0769999996,6451376.6343],[414905.6501000002,6451419.4576],[414983.7874999996,6451315.405],[414978.77660000045,6451203.6776],[415021.0197999999,6451127.2464],[415051.8420000002,6450994.8769],[415029.2346000001,6450855.0812],[414899.8300999999,6450693.4524],[414882.8183000004,6450595.5852],[414776.48950000014,6450517.9117],[414747.5351999998,6450426.9246],[414688.4584999997,6450384.5476],[414605.3772,6450369.8903],[414568.95940000005,6450460.3295],[414555.8437000001,6450606.8071],[414473.11259999964,6450550.2695],[414468.34250000026,6450410.6221],[414433.15529999975,6450354.4835],[414350.7204999998,6450263.0455],[414273.40699999966,6450269.3751],[414076.47389999963,6450365.4401],[414061.89190000016,6450388.7117],[414037.87590000033,6450380.4262],[413891.39940000046,6450430.6506],[413934.48699999973,6450516.7853],[413948.07650000043,6450636.9786],[413961.37650000025,6450791.4776],[414092.2400000002,6450861.1987],[414153.67080000043,6450897.9731],[414179.43510000035,6450913.3962],[414281.23610000033,6450965.7158],[414279.7922,6451137.244],[414352.3854,6451189.3169],[414395.91280000005,6451223.991],[414350.94269999955,6451360.8451],[414495.86280000024,6451439.778]]]]},"geometry_name":"the_geom","properties":{"area":8.09003398112E-5,"Shape_Leng":4319.38797802,"Shape_Area":828429.079784}}]})
However I am not sure how to parse the JSONP response and obtain a property value. I am trying to use the OpenLayers.Format.JSON.read method (not sure if this is the right way to do it) but it returns an error that it is an undefined constructor. Here is my code:
map.events.register('click', map, function (e) {
document.getElementById('nodelist').innerHTML = "Loading... please wait...";
var params = {
REQUEST: "GetFeatureInfo",
EXCEPTIONS: "text/javascript",
BBOX: map.getExtent().toBBOX(),
SERVICE: "WMS",
//use JSONP format
INFO_FORMAT: 'text/javascript',
QUERY_LAYERS: map.layers[0].params.LAYERS,
FEATURE_COUNT: 50,
Layers: 'Bushfire_Com_Study:Fire_Boundary_Pro',
WIDTH: map.size.w,
HEIGHT: map.size.h,
format: format,
styles: map.layers[0].params.STYLES,
srs: map.layers[0].params.SRS,
// handle the wms 1.3 vs wms 1.1 madness
if(map.layers[0].params.VERSION == "1.3.0") {
params.version = "1.3.0";
params.j = parseInt(e.xy.x);
params.i = parseInt(e.xy.y);
} else {
params.version = "1.1.1";
params.x = parseInt(e.xy.x);
params.y = parseInt(e.xy.y);
}
// merge filters
if(map.layers[0].params.CQL_FILTER != null) {
params.cql_filter = map.layers[0].params.CQL_FILTER;
}
if(map.layers[0].params.FILTER != null) {
params.filter = map.layers[0].params.FILTER;
}
if(map.layers[0].params.FEATUREID) {
params.featureid = map.layers[0].params.FEATUREID;
}
OpenLayers.loadURL("http://localhost:8080/geoserver/Bushfire_Com_Study/wms", params, this, setHTML, setHTML);
OpenLayers.Event.stop(e);
});
// sets the HTML provided into the nodelist element
function setHTML(response){
var json_format = new OpenLayers.Format.JSON();
var object = json_format.read(response);
document.getElementById('nodelist').innerHTML = object.features[0].properties['area'];
};
An old question but I couldn't find an answer anywhere else. Most important sources for a solution were
http://dev.openlayers.org/docs/files/OpenLayers/Protocol/Script-js.html
and
http://docs.geoserver.org/stable/en/user/services/wms/vendor.html#wms-vendor-parameters.
My code contained things similar to the following.
// The Script protocol will insert the JSONP response in to the DOM.
var protocol = new OpenLayers.Protocol.Script({
url: someUrl,
callback: someCallbackFunction,
});
// GeoServer specific settings for the JSONP request.
protocol.callbackKey = 'format_options';
protocol.callbackPrefix = 'callback:';
// WMS parameters like in the question
var params={
REQUEST: "GetFeatureInfo",
EXCEPTIONS: "text/javascript",
INFO_FORMAT: 'text/javascript',
//etc
};
// Send the request.
protocol.read({
params: params
});
// Callback to handle the response.
function someCallbackFunction(response) {
for(var feature in response.features) {
// Do something with the returned features.
}
}