This is a migrated thread and some comments may be shown as answers.

Possible CORS error calling my API using $.ajax

7 Answers 970 Views
General Discussion
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Young
Top achievements
Rank 1
Young asked on 01 Dec 2013, 08:25 AM

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.

7 Answers, 1 is accepted

Sort by
0
Steve
Telerik team
answered on 02 Dec 2013, 05:10 PM
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.
0
Young
Top achievements
Rank 1
answered on 02 Dec 2013, 08:33 PM
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?
0
Young
Top achievements
Rank 1
answered on 02 Dec 2013, 10:12 PM

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?
0
Young
Top achievements
Rank 1
answered on 03 Dec 2013, 12:47 AM
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
0
N Mackay
Top achievements
Rank 1
answered on 03 Dec 2013, 09:50 AM
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
                    }
                });            



0
Accepted
Young
Top achievements
Rank 1
answered on 03 Dec 2013, 07:08 PM
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.
0
Iva Koevska
Telerik team
answered on 17 Apr 2014, 03:03 PM
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!

 
Tags
General Discussion
Asked by
Young
Top achievements
Rank 1
Answers by
Steve
Telerik team
Young
Top achievements
Rank 1
N Mackay
Top achievements
Rank 1
Iva Koevska
Telerik team
Share this question
or