Uploaded image for project: 'Apache Cordova'
  1. Apache Cordova
  2. CB-9345

wp8 ajax does not work

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Done
    • Affects Version/s: 3.8.1
    • Fix Version/s: None
    • Labels:
      None
    • Environment:

      -Windows 8.1, Visual Studio 2013 Pro, Cordova 5.1.1, wp8 3.8.1
      -NOKIA Lumia 1520, Windows Phone 8.0

      Description

      wp8 platform builds do not successfully complete ajax requests.

      Note: The 'Affects Version' picker when creating this issue report did not allow me to use the actual version of 3.8.1. I picked the 'unreleased' version of 3.8.0, however, 3.8.1 is the version that is given by default when adding the platform and is listed as a release in github.

      Client Setup

      1. Add wp8 platform: cordova platform add wp8
      2. Add jquery as a dependency in index.html. I used a local copy and did not try cdn.
      3. Change Content-Security-Policy in index.html to have 'default-src' *
      4. Change index.js to the following in order to add tests

      /*
       * Licensed to the Apache Software Foundation (ASF) under one
       * or more contributor license agreements.  See the NOTICE file
       * distributed with this work for additional information
       * regarding copyright ownership.  The ASF licenses this file
       * to you under the Apache License, Version 2.0 (the
       * "License"); you may not use this file except in compliance
       * with the License.  You may obtain a copy of the License at
       *
       * http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing,
       * software distributed under the License is distributed on an
       * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       * KIND, either express or implied.  See the License for the
       * specific language governing permissions and limitations
       * under the License.
       */
      var app = {
          // Application Constructor
          initialize: function() {
              this.bindEvents();
          },
          // Bind Event Listeners
          //
          // Bind any events that are required on startup. Common events are:
          // 'load', 'deviceready', 'offline', and 'online'.
          bindEvents: function() {
              document.addEventListener('deviceready', this.onDeviceReady, false);
          },
          // deviceready Event Handler
          //
          // The scope of 'this' is the event. In order to call the 'receivedEvent'
          // function, we must explicitly call 'app.receivedEvent(...);'
          onDeviceReady: function() {
              app.receivedEvent('deviceready');
          },
          // Update DOM on a Received Event
          receivedEvent: function(id) {
              var parentElement = document.getElementById(id);
              var listeningElement = parentElement.querySelector('.listening');
              var receivedElement = parentElement.querySelector('.received');
      
              listeningElement.setAttribute('style', 'display:none;');
              receivedElement.setAttribute('style', 'display:block;');
      
              console.log('Received Event: ' + id);
      
              console.log('Running connection test');
              testConnections();
          }
      };
      
      // You will need to change this to match your machine ip
      var url = "http://test:1337/test/test";
      
      function testConnections() {
          console.log("Sending requests...");
          try {
              jqueryGet();
              jqueryPost();
              post();
              get();
          } catch (e) {
              console.error(e);
              console.log(e);
          }
      }
      
      function jqueryGet() {
          $.ajax(url, {
              type: 'GET',
              dataType: 'json',
              contentType: 'application/json;charset=utf-8',
              processData: false,
              data: JSON.stringify({
                  userName: 'asmith'
              }),
              complete: function (jqXHR, textStatus) {
                  console.log("JQUERY GET: ");
                  console.log(JSON.stringify(jqXHR, null, 2));
              }
          });
      }
      
      function jqueryPost() {
          $.ajax(url, {
              type: 'POST',
              dataType: 'json',
              contentType: 'application/json;charset=utf-8',
              processData: false,
              data: JSON.stringify({
                  userName: 'asmith'
              }),
              complete: function (jqXHR, textStatus) {
                  console.log("JQUERY POST");
                  console.log(JSON.stringify(jqXHR, null, 2));
              }
          });
      }
      
      function post() {
          var xmlHttp = new XMLHttpRequest();
          var parameters = '{"userName" : "asmith"}';
          xmlHttp.open("POST", url, true);
      
          xmlHttp.setRequestHeader("Content-type", "application/json;charset=utf-8");
      
          xmlHttp.onreadystatechange = function() {
              console.log("POST ready state: " + xmlHttp.readyState);
              console.log(JSON.stringify(xmlHttp, null, 2));
          };
      
          xmlHttp.send(parameters);
      }
      
      
      function get() {
          var request = new XMLHttpRequest();
          request.open('GET', url, true);
      
          request.onload = function() {
              if (this.status >= 200 && this.status < 400) {
                  // Success!
                  console.log('GET: ' + this.response);
              } else {
                  console.log('GET: error in onload');
                  console.log(JSON.stringify(this, null, 2));
              }
          };
      
          request.onerror = function() {
              console.log('GET: error in onerror');
              console.log(JSON.stringify(this, null, 2));
          };
      
          request.send('{"userName" : "asmith"}');
      }
      app.initialize();
      

      config.xml is unchanged, but does include white list plugin default setting <access origin="*" />.

      Server Setup
      I created a simple sails.js server for the test, but am using a client's IIS server in production. Use any server for reproducing.

      1. Install node.js
      2. Install sails: npm install -g sails
      3. Create sails app: sails new testAjaxServer
      4. Create controller file for testing <root>/api/TestController.js and populate it with

      module.exports = {
        test : function (req, res) {
          sails.log("Got a request");
          res.send('{"result":"hooray!"}');
        }
      };
      

      5. Run the server from the root directory of the sails app: sails lift
      6. Test server by visiting localhost:1337/test/test. You should see the json result that is specified in the test controller.

      Expected
      Loading this index.html in chrome and running testConnections() produces the correct output as shown below.

      Sending requests...
      undefined
      index.js:136 GET: {"result":"hooray!"}
      index.js:88 JQUERY GET: 
      index.js:89 {
        "readyState": 4,
        "responseText": "{\"result\":\"hooray!\"}",
        "responseJSON": {
          "result": "hooray!"
        },
        "status": 200,
        "statusText": "OK"
      }
      index.js:119 POST ready state: 2
      index.js:120 {
        "response": "",
        "responseText": ""
      }
      index.js:119 POST ready state: 3
      index.js:120 {
        "response": "{\"result\":\"hooray!\"",
        "responseText": "{\"result\":\"hooray!\""
      }
      index.js:104 JQUERY POST
      index.js:105 {
        "readyState": 4,
        "responseText": "{\"result\":\"hooray!\"}",
        "responseJSON": {
          "result": "hooray!"
        },
        "status": 200,
        "statusText": "OK"
      }
      index.js:119 POST ready state: 3
      index.js:120 {
        "response": "{\"result\":\"hooray!\"}",
        "responseText": "{\"result\":\"hooray!\"}"
      }
      index.js:119 POST ready state: 4
      index.js:120 {
        "response": "{\"result\":\"hooray!\"}",
        "responseText": "{\"result\":\"hooray!\"}"
      }
      

      Actual
      Running the same code deployed to a wp8 device produces the following.

      Received Event: deviceready
      Running connection test
      Sending requests...
      POST ready state: 1
      {
        "wrappedXHR": {},
        "readyState": 1
      }
      JQUERY POST
      {
        "readyState": 4,
        "responseText": "",
        "status": 200,
        "statusText": "parsererror"
      }
      POST ready state: 4
      JQUERY GET: 
      {
        "readyState": 4,
        "responseText": "",
        "status": 200,
        "statusText": "parsererror"
      }
      {
        "wrappedXHR": {},
        "readyState": 4
      }
      GET: error in onload
      {
        "wrappedXHR": {},
        "readyState": 4
      }
      

      The jquery functions have a 200 response, but fail due to a 'parserror'. There is no response text. The vanilla js tests fail for an undisclosed reason. The server logs indicate that there was never any established connection. I am able to hit my server from the phone's browser and get the json response.

      Interestingly, when running the test in IE11 I get the following error: SCRIPT7002: XMLHttpRequest: Network Error 0x2efd, Could not complete the operation due to error 00002efd.. There could be a similar error occurring in the device, but I am not sure how to capture it. In any case, I believe that I have followed all of the documentation for settings up the test project for using ajax calls, so if there is other configuration required then at least there needs to be a doc update.

        Attachments

          Activity

            People

            • Assignee:
              purplecabbage Jesse MacFadyen
              Reporter:
              adammatthewsmith Adam M. Smith
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: