locked
Access web service from device RRS feed

  • Question

  • User767580559 posted

    I'm attempting to make ajax calls from an android device to a web service, but receiving the following error:

    Apache Cordova: Failed to load resource: the server responded with a status of 404 (Not Found)

    I've been able to access the service from the simulator with no problem. Here's a sample of the code:

    var sUrl = "http://localhost:52437/MyServiceContract.svc/Read_Customer/" + $("#txtDeviceId").val();
    
        var jqxhr = $.getJSON(sUrl, function () {
                // do nothing
            alert('this is a test');
        }).done(function (data) { 
    var jsonData = JSON.stringify(data);
            var objData = $.parseJSON(jsonData);
    }).fail(function (result) {            
                CustomerServiceFailed(result); // When Service call fails                                    
            });
    
        return jqxhr;
    

    Although, I'm trying to access the service from localhost, the service runs successfully on the device using Chrome when ADB reverse socket is implemented. That is, the url is entered into web browser and data is returned. Here's a sample of the ADB command:

    adb.exe reverse tcp:4000 tcp:4000

    Lastly, I also moved the service to IIS but received the same 404 on the device. The service on IIS can be reached from the simulator, as well.

    Any help is appreciated.

    Saturday, May 12, 2018 7:09 PM

All replies

  • User475983607 posted

    I've never build a Cordova app before so I gave it a shot and it just worked.  i had a couple of hiccups but they were just coding errors.  I'm using VS 2017 Version 15.7.1.  I had to install Cordova using the Visual Studio installer.

    I create a solution with 3 default template projects; Cordova Empty, Web API, and MVC.  I used Web API in place of WCF as Web API is easier and has a richer REST environment.  But WCF REST should work if it's configured correctly.  First I configured IIS to host the Web API project from the project properties in Visual Studio.  Next enabled CORS in the Web API project.  I verified the Web API app using the MVC app and Chrome same as the tutorial.  

    @{
        ViewBag.Title = "Home Page";
    }
    
    <div>
        <select id="method">
            <option value="get">GET</option>
            <option value="post">POST</option>
            <option value="put">PUT</option>
        </select>
        <input type="button" value="Try it" onclick="sendRequest()" />
        <span id='value1'>(Result)</span>
    </div>
    
    @section scripts {
        <script>
            // TODO: Replace with the URL of your WebService app
            var serviceUrl = 'http://192.168.1.124/WebApiService/api/values';
    
            function sendRequest() {
                var method = $('#method').val();
    
                $.ajax({
                    type: method,
                    url: serviceUrl
                }).done(function (data) {
                    $('#value1').text(data);
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    $('#value1').text(jqXHR.responseText || textStatus);
                });
            }
        </script>
    }

    From this point, I followed this tutorial https://docs.microsoft.com/en-us/visualstudio/cross-platform/tools-for-cordova/first-steps/build-your-first-app?view=toolsforcordova-2017 but replaced the weather service with my Web API service.  The UI and JavaScript is based on the MVC test app above.

    My index.html.  Note: I updated the <meta http-equiv="Content-Security-Policy"...  tag with the service endpoint.

    <!DOCTYPE html>
    <html>
        <head>
        <!--
            Customize the content security policy in the meta tag below as needed. Add 'unsafe-inline' to default-src to enable inline JavaScript.
            For details, see http://go.microsoft.com/fwlink/?LinkID=617521
        -->
            <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: http://192.168.1.124/WebApiService/api/values https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
            
            <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
            <meta name="format-detection" content="telephone=no">
            <meta name="msapplication-tap-highlight" content="no">
            <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
            <link rel="stylesheet" type="text/css" href="css/index.css">
            <title>CordovaClient</title>
        </head>
        <body>
            <div class="app">
                <div>
                    <input id="button" type="button" value="Try it" />
                    <span id='value1'>(Result)</span>
                </div>
            </div>
            <script type="text/javascript" src="cordova.js"></script>
            <script type="text/javascript" src="scripts/platformOverrides.js"></script>
            <script type="text/javascript" src="scripts/index.js"></script>
            <script src="scripts/jquery-3.3.1.js"></script>
            <script src="scripts/jquery.mobile-1.4.5.js"></script>
    
            <script src="scripts/webapiclient.js"></script>
    
        </body>
        </html>
    

    Modified default index.js

    // For an introduction to the Blank template, see the following documentation:
    // http://go.microsoft.com/fwlink/?LinkID=397704
    // To debug code on page load in cordova-simulate or on Android devices/emulators: launch your app, set breakpoints, 
    // and then run "window.location.reload()" in the JavaScript Console.
    (function () {
        "use strict";
    
        document.addEventListener( 'deviceready', onDeviceReady.bind( this ), false );
    
        function onDeviceReady() {
            // Handle the Cordova pause and resume events
            document.addEventListener( 'pause', onPause.bind( this ), false );
            document.addEventListener('resume', onResume.bind(this), false);
    
            $('#button').click(invokeWebAPI);
            
        }
    
        function onPause() {
            // TODO: This application has been suspended. Save application state here.
        }
    
        function onResume() {
            // TODO: This application has been reactivated. Restore application state here.
        }
    
    
    
    } )();

    The webapiclient.js file is custom and contains the jQuery AJAX code.

    function invokeWebAPI() {
        var serviceUrl = 'http://192.168.1.124/WebApiService/api/values';
        $.ajax({
            type: 'GET',
            url: serviceUrl
        }).done(function (data) {
            $('#value1').text(data);
        }).fail(function (jqXHR, textStatus, errorThrown) {
            $('#value1').text(jqXHR.responseText || textStatus);
        });
    }

    I connected my android device using -> https://developer.android.com/studio/command-line/adb

    Then ran app on the device.  clicked the button and "VALUE1, VALUE2" rendered to the UI.

    namespace WebApiService.Controllers
    {
        [EnableCors(origins: "*", headers: "*", methods: "*")]
        public class ValuesController : ApiController
        {
            // GET api/values
            public IEnumerable<string> Get()
            {
                return new string[] { "value1", "value2" };
            }

    Sunday, May 13, 2018 1:01 AM
  • User-474980206 posted

    because the simulator is running on your box "localhost" will work (reference the website). but when you run in a real device, localhost is that device. you should use the ip address of the box not localhost. to access remotely. the device must b on your local lan, and you will probably need to open the firewall for your custom port number.  

    Sunday, May 13, 2018 11:15 PM
  • User767580559 posted

    Hi Bruce,

    Thanks for the reply. It's appreciated. I think I need to change to ip address as well but I was hesitate to do so for two (2) reasons:

    1. I was able to access the service from Chrome on the device using localhost in the url.
    2. I moved the service to a host and changed the ajax call to include the url of the host and the same error was returned.

    Monday, May 14, 2018 6:51 PM
  • User753101303 posted

    Hi,

    My first move would be to check the server side IIS log. Do you see 404 errrors? For now I'm trying to understand if the http query reaches the expected web site.

    My understanding is that you are trying to reach a web service from a real device (you are on the same network?) which runs a Cordova app. If you need further help a dedicated Cordova forum could be better.

    Monday, May 14, 2018 7:12 PM
  • User767580559 posted

    Hello,

    I had to add to CSP directives to both the meta tag and config.xml, for the app to run on the device. Thanks to all for their help.

    Wednesday, May 16, 2018 9:17 PM