Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development Knowledge Base

Using XMLHttpRequest from QML in Cascades to access web services

by Developer on ‎04-08-2013 10:23 AM (7,378 Views)

Passing data back and forth between QML and C++ is (relatively) quite a lot of work and complicates apps.  A lot of the performance benefit is lost in converting data types (particularly JSON -> QVariant<List/Map> structures -> JavaScript® Objects is a bit crazy if you ask me). If you don't need to do much processing of the data then simply accessing the network from JavaScript is much more convenient.  If you're accessing a webservice that uses JSON then it's ideal.


The good news is that this does work.  Only asynchronous requests are supported and if you don't check that the request readyState is DONE before querying the request status then you get "Invalid state" errors that are just attributed to the relevant QML file rather than any specific bit of code. Below is some skeleton code for a POST request but others work similarly:

function submitPost(postString) {
                var request = new XMLHttpRequest();
                request.onreadystatechange=function() {
                    // Need to wait for the DONE state or you'll get errors
                    if(request.readyState === XMLHttpRequest.DONE) {
                        if (request.status === 200) {
                            console.log("Response = " + request.responseText);
                            // if response is JSON you can parse it
                            var response = JSON.parse(request.responseText);
                            // then do something with it here
                        else {
                            // This is very handy for finding out why your web service won't talk to you
                            console.log("Status: " + request.status + ", Status Text: " + request.statusText);
                // Make sure whatever you post is URI encoded
                var encodedString = encodeURIComponent(postString);
                // This is for a POST request but GET etc. work fine too
                request.open("POST", "https://<your_service_endpoint_here>", true); // only async supported
                // You might not need an auth header, or might need to modify - check web service docs
                request.setRequestHeader("Authorization", "Bearer " + yourAccessToken);
                // Post types other than forms should work fine too but I've not tried
                request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                // Form data is web service dependent - check parameter format
                var requestString = "text=" + encodedString;

The other good news is that JSON.parse() and JSON.stringify() are also available (so please don't use eval). 


While researching this I discovered that *apparently* adding elements to a ListModel in JavaScript is very slow compared to C++, so you don't want to do it with very large numbers of objects.  That said, there are pure QML/JS Twitter® clients with decent performance on slow old Symbian devices.  I can't confirm how slow because:

"Currently, you can use the profiler only for C++ code. You can't use the profiler for QML or JavaScript code." 


If you've only got fairly small amounts of data to pass around, particularly if it's JSON, then this is a more convenient way of accessing web services with minimal performance impact.  Being able to do this kind of simple web-connected app entirely in QML/JS was part of the original vision for the language - at least for prototyping.

by Developer
on ‎02-25-2016 07:35 AM

Just to mention that Qt 4.8 doesn't support all HTTP Verbs out of the box. For instance, PATCH and OPTIONS have to be done using QNetworkAcessManager::sendCustomRequest.


But beware because Qt 4.8 has a bug with this function when trying to post some data. You can find an independent patch for it here.


Good luck.

by Developer
on ‎02-26-2016 09:58 AM

Thanks to the help of the users from the Support Forums, I was able to make the sendCustomRequest work. So you can disregard the bug I mentioned.


This is the reference implementation:

    QVariantMap toJson;

    QVariantList body;

    JsonDataAccess jda;
    QString sbody;

    jda.saveToBuffer(body, &sbody);

    if( jda.hasError() ){
        qWarning() << "jda.error.errorMessage:" << jda.error().errorMessage();
        qDebug() << "sbody:" << sbody;

    QByteArray bodyData;

    QBuffer *buffer = new QBuffer();

    QByteArray bearer;
    bearer.append("Bearer ");

    QNetworkRequest req( QUrl(buildUrl(toJson) ));
    req.setRawHeader("Authorization", bearer);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    QNetworkReply *reply = m_networkAcessManager->sendCustomRequest(req, "PATCH", buffer);

Users Online
Currently online: 26 members 1,515 guests
Please welcome our newest community members: