Possible CORS error calling my API using $.ajax

8 posts, 1 answers
  1. Young
    Young avatar
    13 posts
    Member since:
    Nov 2013

    Posted 01 Dec 2013 Link to this post

    I'm using Icenium to develop a native app. Currently just built one sample hybrid application using icenium (www.icenium.com) to call API using jQuery ajax, but still getting some errors saying "Possible CORS error!" in Icenium.

    I've read through how I can implement CORS headers to allow cross domain ajax, however seems it is still not working in my native app built through icenium.

    Here's my response header:

    Content-Length: 76 
    Content-Language: en 
    Status_code: 200
    Vary: Accept-Language, Cookie 
    Allow: GET, POST, PUT 
    Date: Sun, 01 Dec 2013 08:22:56 GMT 
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Headers: Content-Type
    Content-Type: application/json 
    X-Frame-Options: SAMEORIGIN
    Does any one see any problems? This API call works just fine in my browser (as an web app) but not on Mist and the build app on my android. It returns $.ajax.error function.
  2. Steve
    Admin
    Steve avatar
    10941 posts

    Posted 02 Dec 2013 Link to this post

    Hello Young,

    You would have this error only in Mist as it is a browser based i.e. your requests are coming from icenium.com and CORS issues would arise. For more information refer to this forum post.

    Regards,
    Steve
    Telerik
    You've missed the Icenium Visual Studio Integration keynote? It has been recorded and posted here.
    Looking for tips & tricks directly from the Icenium team? Check out our blog!
    Share feedback and vote for features on our Feedback Portal.
  3. Young
    Young avatar
    13 posts
    Member since:
    Nov 2013

    Posted 02 Dec 2013 Link to this post

    Even though my API server returns 
    Access-Control-Allow-Origin: *

    my API call using jQuery is failing on the physical device. But it works in Chrome (on my desktop when running as a web app). Any clue?
  4. Young
    Young avatar
    13 posts
    Member since:
    Nov 2013

    Posted 02 Dec 2013 Link to this post


    how can you explain this problem? 
    Now it works on Mist, but still not on my physical device...

    I get
    {"status":0, "statusText": "error", "responseText": "", "readyState": 0} if I return xhr.statusCode()

    btw, my call the the api uses https connection. Would this matter?
  5. Young
    Young avatar
    13 posts
    Member since:
    Nov 2013

    Posted 02 Dec 2013 Link to this post

    Oh. seems like this is https issue, because my qa server does not use valid certification. Is this right?
    http://stackoverflow.com/questions/14649105/phonegap-android-https-requests-not-working-when-built-through-eclipse
  6. N Mackay
    N Mackay avatar
    228 posts
    Member since:
    Dec 2010

    Posted 03 Dec 2013 Link to this post

    Hi Young,

    We have implemented Rest and WebAPI WCF services for Icenium and both work in Graphite and Mist and work in iOS/Android & Blackberry. We only allow specific domains to gets a 200 response rather than anyone which * allows.

    Every call must return a pre-flight OK before returning data. You might have to use JSON-P if it's not your data service but that approach is limited if you want to return meaningful Status codes etc.

    A WCF REST API approach is shown below, not saying it's perfect but it does work fine with HTTPS :-)


    SERVICE

            public dtCustomer GetCustomerDetails(string CustomerID)
            {

                try
                {

                    // Check for browser pre-flight CORS request

                    if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
                    {
                        AllowCORS();
                        return null;
                    }

            Get Data
            AllowCORS(); -- SEND back 200 again or the browser will grumble
                    Return Customer;


            private void AllowCORS()
            {

                // Get the request headers
                WebHeaderCollection headers = WebOperationContext.Current.IncomingRequest.Headers;
                
                if (IsCORSAllowed(headers["Origin"]))
                {
                    // Allow the cross domain call
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", headers["Origin"]);
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "GET");
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST");
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, SomethingCustom");

                    // Stop ajax caching the responses on Safari/iOS
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Pragma", "no-cache");
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
                    WebOperationContext.Current.OutgoingResponse.Headers.Add("Expires", "0");
                }
            }


            private bool IsCORSAllowed(string RequestURL)
            {

                try
                {

                    if (RequestURL != null)
                    {
                        List<string> SafeHosts = new List<string>(ConfigurationManager.AppSettings["CORSRequest"].Split(';'));
                        return SafeHosts.Any(RequestURL.Contains);
                    }
                    else
                    {
                        return false;
                    }
                }


    CLIENT:

                           $.ajax({
                        type: "POST",
                        url: "https://MyURL:MyPort/MyService.svc/GetCustomer",
                        contentType: "application/json",
                        beforeSend: function (xhr) {
                            xhr.setRequestHeader('Somethingtopass', SomeValue);
                        },
                        data: JSON.stringify(e.dataItem.CustomerId),
                        dataType: "json",
                        cache: false,
                        success: function(msg) {
                            customerResponse(msg);
                        },
                        statusCode: {
                            400: function(jxhr, textStatus, errorThrown) {
                            },
                            401: function() {
                            }
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                            // general error
                        }
                    });            



  7. Answer
    Young
    Young avatar
    13 posts
    Member since:
    Nov 2013

    Posted 03 Dec 2013 Link to this post

    my production server has valid SSL cert but not my test server.
    I've changed HTTPS to HTTP for my test server and it works now.
  8. Iva Koevska
    Admin
    Iva Koevska avatar
    286 posts

    Posted 17 Apr 2014 Link to this post

    Hello all,

    If you're using the in-browser client in Chrome, you can get the Telerik AppBuilder Helper for Chrome which enables Ajax CORS requests for the device simulator to spare you the CORS errors.

    You can get it from here. The team plans to bring more improvements in the Helper in the future, so keep an eye on it.

    Regards,
    Iva Koevska
    Telerik
     

    Share what you think about AppBuilder and Telerik Platform with us in our feedback portal, so we can become even better!

     
Back to Top