Titanium isn't posting values to ColdFusion - post

This is my Titanium code:
var loginReq = Titanium.Network.createHTTPClient({
onload: function(e){
// just displays the response
var webview = Titanium.UI.createWebView({html:this.responseText});
win.add(webview);
}
});
loginReq.open("POST",url);
var params = {
email: email.value,
passowrd: password.value
};
loginReq.send(params); // this is sending nothing according to a CF variable dump
The ColdFusion page just dumps all the variables, and it shows up on the iPhone emulator. But it's giving me an empty struct for the variables, which means no variables are actually getting sent in.
How do I fix my Titanium code to actually post data?

If you want to send post data to a script you will have to to set the header accordingly:
loginReq.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
If you are sending JSON data to an API, you might need to stringify your parameters to send them:
loginReq.send(JSON.stringify(params));
Edit:
According to the docs this is done automatically (see comments). In some of my network clients I had to do that explicitly, though...
Moreover, you might also want to implement the onerror callback, so in case your call fails for any reason you will know why:
var loginReq = Titanium.Network.createHTTPClient({
onload: function(e){
// just displays the response
var webview = Titanium.UI.createWebView({html:this.responseText});
win.add(webview);
},
onerror: function(e) {
Ti.API.debug('Status: ' + this.status);
Ti.API.debug('Response: ' + this.responseText);
}
});

Related

Appcelerator - Getting geolocation information and turning into a URL

I'm still very new to appcelerator but I'm trying to do a small experiment with geolocation. I have some code similar to below, which returns the long and lat to the console. What I would like to is get the long and lat and append them to a URL, e.g http://www.mywebsite.com/lat/long.
I've tried creating a simple alert to show me the current location in the but all it says is Alert: [object GeolocationModule].
Could somebody point me in the right direction so I can learn some more? Thank you
if (Ti.Geolocation.locationServicesEnabled) {
Titanium.Geolocation.purpose = 'Get Current Location';
Titanium.Geolocation.getCurrentPosition(function(e) {
if (e.error) {
Ti.API.error('Error: ' + e.error);
} else {
Ti.API.info(e.coords);
}
});
} else {
alert('Please enable location services');
}
This is how you need to follow the API documentation:
You can have a look at the LocationResults page: https://docs.appcelerator.com/platform/latest/#!/api/LocationResults which leads you to LocationCoordinates: https://docs.appcelerator.com/platform/latest/#!/api/LocationCoordinates
There you can see, that you can use e.coords.latitude or longitude to get the values. Or have a look at the console output. It should show you a JSON output with the key-value pairs.
Once you have the values you can create a HTTP request (demo: https://docs.appcelerator.com/platform/latest/#!/guide/HTTPClient_and_the_Request_Lifecycle) and open your page:
var url = "https://www.appcelerator.com/"+e.coords.longitude+"/"+e.coords.latitude;
var xhr = Ti.Network.createHTTPClient({
onload: function(e) {
// this function is called when data is returned from the server and available for use
// this.responseText holds the raw text return of the message (used for text/JSON)
// this.responseXML holds any returned XML (including SOAP)
// this.responseData holds any returned binary data
Ti.API.debug(this.responseText);
alert('success');
},
onerror: function(e) {
// this function is called when an error occurs, including a timeout
Ti.API.debug(e.error);
alert('error');
},
timeout:5000 /* in milliseconds */
});
xhr.open("GET", url);
xhr.send(); // request is actually sent with this statement
or if you plan to use more request have a look at RESTe (https://github.com/jasonkneen/RESTe) which is an awesome library that makes it easy to create API requests

Titanium Appcelerator API call error - HTTP ERROR

I am having a website which contains login page. When user tries to log in using username and password. Data is being passed in Form Data. Please have a look as following image to get idea.
Now I want to use the same api in my Titanium application and get all details or logged in user which i am performing using below mentioned code.
var url= "http://www.randomwebsite.com/login/";
var jsonData = {
username: "admin",
password: "password1"
};
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function(e) {
var obj = JSON.parse(this.responseText);
alert("DATA IS " + JSON.stringify(obj));
};
xhr.onerror = function(e) {
Ti.API.info("ERROR " + e.error);
};
xhr.onsendstream = function(e){
Ti.API.info("onsendstream");
};
xhr.ondatastream = function(e){
Ti.API.info("ondatastream");
};
xhr.open('POST',url);
xhr.send(JSON.stringify(jsonData));
I am getting HTTP error. I even tried setting xhr.setHeader('Content-Type','application/json') as well as verified url its same as that is being used by website. Can any one help me out with this ? Or is there any way in order to make sure that titanium code passes data in form-data ? Or any suggestion regarding this would be of great help.
Its working fine now. Mistake that I was doing is that i was stringifying text when data was being send. So changing xhr.send(JSON.stringify(jsonData)) to xhr.send(jsonData) works for me. Hope so this would help some one.

Working with XML in a Firefox Add-on(ex Jetpack)

I'm currently developing a Firefox add-on(using https://addons.mozilla.org/en-US/developers/docs/sdk/1.0/ ) that consumes an API where the return data is in xml.
My problem is that I need to parse the returned data, and would like to do that using a xml object.
Since the request module only supports JSON and Text ( https://addons.mozilla.org/en-US/developers/docs/sdk/1.0/packages/addon-kit/docs/request.html#Response ) I need to convert the response.text to XML.
The code looks like this:
var Request = require('request').Request
.......
var req = Request({
url: https://to-the-api.com,
content: {
op: 'get-the-data-op',
password: "super-sec",
user: "username"
},
onComplete: function (response) {
dataAsText = response.text;
console.log("output: " + dataAsText);
}
});
req.post();
I have tried to user (new DOMParser).parseFromString(response.text, 'text/xml') but unfortunately it just fails with a error like ReferenceError: DOMParser is not defined
The question is if anyone of you guys have been able to create a Xml object inside a Firefox add-on, and if so, how?
Looks like the capability to parse response as xml was present, but has been removed. check out this bugzilla reference
Can't you use a normal XMLHttpRequest if you want to process the response as XML?
If DOMParser is unavailable you can try E4X:
var xml = new XML(response.text);
alert(xml.children().length());
You want to use the XMLHttpRequest object to handle your xhr request. Then when you get a response back access the responseXML object of the request variable. In the responseXML you'll have the documentElement and can use the querySelectorAll or querySelector to find elements you want. In each element you want just grab the textContent you need.
Here's an example to get you going (this looks for the 'xmls' element in the response):
var request = new require("xhr").XMLHttpRequest();
request.open('GET', 'https://to-the-api.com', true);
request.onreadystatechange = function (aEvt) {
if (request.readyState == 4) {
if(request.status == 200) {
var xmls = request.responseXML.documentElement.querySelectorAll("xmls");
for (var i = 0; i < xmls.length; i++) {
console.log("xml", i, xmls[i], xmls[i].textContent);
}
}
else {
console.log('Error', request.responseText);
}
}
};
request.send(null);

two way communication between extension and content javascript files

i am trying to accomplish a two way communication request response in my firefox sidebar extension, i have a file named event.js this resides on the content side, i have another file called sidebar.js file which is residing in the xul. I am able to communicate from event.js to sidebar.js file using the dispatchEvent method. my event in turn raises a XMLHttpRequest in sidebar.js file which hits the server and sends back the response. Now, here i am unable to pass the response to the event.js file. I want the response to be accessed in the event.js file. Till now i have achieved only one way communication. Please help me in getting the two way communication.
Code is as follows:
// event.js file
// This event occurs on blur of the text box where i need to save the text into the server
function saveEvent() {
var element = document.getElementById("fetchData");
element.setAttribute("urlPath", "http://localhost:8080/event?Id=12");
element.setAttribute("jsonObj", convertToList);
element.setAttribute("methodType", "POST");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("saveEvent", true, true);
element.dispatchEvent(evt);
//Fetching the response over here by adding the listener
document.addEventListener("dispatchedResponse", function (e) { MyExtension.responseListener(e); }, false, true);
}
var MyExtension = {
responseListener: function (evt) {
receivedResponse(evt.target.getAttribute("responseObject"));
}
}
function receivedResponse(event) {
alert('response: ' + event);
}
// sidebar.js file
window.addEventListener("load", function (event) {
var saveAjaxRequest = function (urlPath, jsonObj, methodType, evtTarget) {
var url = urlPath;
var request = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function (aEvent) {
window.alert("Response Text: " + aEvent.target.responseText);
saveResponse = aEvent.target.responseText;
//here i am again trying to dispatch the response i got from the server back to the origin, but unable to pass it...
evtTarget.setAttribute("responseObject", saveResponse);
document.documentElement.appendChild(evtTarget);
var evt = document.createEvent("dispatchedRes"); // Error line "Operation is not supported" code: "9"
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
};
request.onerror = function (aEvent) {
window.alert("Error Status: " + aEvent.target.status);
};
//window.alert(methodType + " " + url);
request.open(methodType, url, true);
request.send(jsonObj);
};
this.onLoad = function () {
document.addEventListener("saveEvent", function (e) { MyExtension.saveListener(e); }, false, true);
}
var MyExtension =
{
saveListener: function (evt) {
saveAjaxRequest(evt.target.getAttribute("urlPath"), evt.target.getAttribute("jsonObj"), evt.target.getAttribute("methodType"), evt.originalTarget);
}
};
});
Why are you moving your fetchData element into the sidebar document? You should leave it where it is, otherwise your content code won't be able to receive the event. Also, use the content document to create the event. Finally, document.createEvent() parameter for custom events should be "Events". So the code after your //here i am again trying comment should look like:
evtTarget.setAttribute("responseObject", saveResponse);
var evt = evtTarget.ownerDocument.createEvent("Events");
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
Please note however that your code as you show it here is a huge security vulnerability - it allows any website to make any HTTP requests and get the result back, so it essentially disables same-origin policy. At the very least you need to check that the website talking to you is allowed to do it (e.g. it belongs to your server). But even then it stays a security risk because server response could be altered (e.g. by an attacker on a public WLAN) or your server could be hacked - and you would be giving an attacker access to sensitive data (for example he could trigger a request to mail.google.com and if the victim happens to be logged in he will be able to read all email data). So please make this less generic, only allow requests to some websites.

ASP.NET MVC ajax chat

I built an ajax chat in one of my mvc website. everything is working fine. I am using polling. At certain interval i am using $.post to get the messages from the db. But there is a problem. The message retrieved using $.post keeps on repeating. here is my javascript code and controller method.
var t;
function GetMessages() {
var LastMsgRec = $("#hdnLastMsgRec").val();
var RoomId = $("#hdnRoomId").val();
//Get all the messages associated with this roomId
$.post("/Chat/GetMessages", { roomId: RoomId, lastRecMsg: LastMsgRec }, function(Data) {
if (Data.Messages.length != 0) {
$("#messagesCont").append(Data.Messages);
if (Data.newUser.length != 0)
$("#usersUl").append(Data.newUser);
$("#messagesCont").attr({ scrollTop: $("#messagesCont").attr("scrollHeight") - $('#messagesCont').height() });
$("#userListCont").attr({ scrollTop: $("#userListCont").attr("scrollHeight") - $('#userListCont').height() });
}
else {
}
$("#hdnLastMsgRec").val(Data.LastMsgRec);
}, "json");
t = setTimeout("GetMessages()", 3000);
}
and here is my controller method to get the data:
public JsonResult GetMessages(int roomId,DateTime lastRecMsg)
{
StringBuilder messagesSb = new StringBuilder();
StringBuilder newUserSb = new StringBuilder();
List<Message> msgs = (dc.Messages).Where(m => m.RoomID == roomId && m.TimeStamp > lastRecMsg).ToList();
if (msgs.Count == 0)
{
return Json(new { Messages = "", LastMsgRec = System.DateTime.Now.ToString() });
}
foreach (Message item in msgs)
{
messagesSb.Append(string.Format(messageTemplate,item.User.Username,item.Text));
if (item.Text == "Just logged in!")
newUserSb.Append(string.Format(newUserTemplate,item.User.Username));
}
return Json(new {Messages = messagesSb.ToString(),LastMsgRec = System.DateTime.Now.ToString(),newUser = newUserSb.ToString().Length == 0 ?"":newUserSb.ToString()});
}
Everything is working absloutely perfect. But i some messages getting repeated. The first time page loads i am retrieving the data and call GetMessages() function. I am loading the value of field hdnLastMsgRec the first time page loads and after the value for this field are set by the javascript.
I think the message keeps on repeating because of asynchronous calls. I don't know, may be you guys can help me solve this.
or you can suggest better way to implement this.
Kaivalya is correct about the caching, but I'd also suggest that your design could and should be altered just a tad.
I made a very similar app recently, and what I found was that my design was greatly enhanced by letting the controllers work with the fairly standard PRG pattern (post-redirect-get). Why enhanced? well, because POST methods are built to add stuff to an app, GET methods are supposed to be used to get information without side effects. Your polling should be just getting new messages w/o side effects.
So rather than your $.post call expecting data and handling the callback, what I'd recommend is having your controller expose a method for creating new chat messages via POST and then another method that get the last X chat messages, or the messages since a certain timestamp or whatever.
The javascript callback from the post action, then can update some variables (e.g. the last message id, timestamp of the last message, or even the whole URL of the next message based on the info contained in a redirect, whatever).
The $.post would fire only in response to user input (e..g type in a box, hit 'send') Then, you have (separately) a $.get call from jquery that's set up to poll like you said, and all it does is fetch the latest chat messages and it's callback updates the chat UI with them.
I got my answer here: ASP.NET AJAX CHAT
The names below i am referring to are from above link.
i think the actual problem was with the timestamp thing and asynchronous behaviour of $.post. after calling "GetMessages()" method, even if the previous request to retrive chat message was not complete anathor call to same method used to fire due to setting timeout for "GetMessages()" method outside the $.post method. In my question you can see that timeout for "GetMessages()" method is set outside the $.post method. Now i set the timeout for "GetMessages()" method inside the $.post method. so that next call to "GetMessages()" only occur after 3 seconds of completion of current $.post method. I have posted the code below.
var t;
function GetMessages() {
var LastMsgRec = $("#hdnLastMsgRec").val();
var RoomId = $("#hdnRoomId").val();
//Get all the messages associated with this roomId
$.post("/Chat/GetMessages", { roomId: RoomId, lastRecMsg: LastMsgRec }, function(Data) {
if (Data.LastMsgRec.length != 0)
$("#hdnLastMsgRec").val(Data.LastMsgRec);
if (Data.Messages.length != 0) {
$("#messagesCont").append(Data.Messages);
if (Data.newUser.length != 0)
$("#usersUl").append(Data.newUser);
$("#messagesCont").attr({ scrollTop: $("#messagesCont").attr("scrollHeight") - $('#messagesCont').height() });
$("#userListCont").attr({ scrollTop: $("#userListCont").attr("scrollHeight") - $('#userListCont').height() });
}
else {
}
t = setTimeout("GetMessages()", 3000);
}, "json");
}
I addition to that i also changed few things. As suggested by ignatandrei i placed $("#hdnLastMsgRec").val(Data.LastMsgRec); immediately after function(Data) {.
and also
as said by MikeSW i changed the data retrieval process. Previously i was extracting data on the basis of timespan(retrieve all the data associated with
this room id that has greater timespan than last data retrieved message timespan) but now i keep track of the messageid. Now i retrieve only those data that
has message id greater than last retrieved message id.
and guess what no repeataion and perfectly working chat application so far on my intranet.
I still got to see it's performance when deployed on internet.
i think it solved my problem.
i will still test the system and let u guys know if there is any problem.
By default $.post() caches the results
You can either call $.ajaxSetup ({ cache: false}); before JS GetMessages function call to ensure caching is disabled or change the $.post to $.ajax and set cache attribute to false. In the end $.post() is a short cut to this:
$.ajax({
type: 'POST',
url: url,
data: data,
success: success
dataType: dataType
});

Resources