15

I am learning angularJS and trying to implement it in my application.

I have an RESTful WCF service hosted on localhost IIS. It has a GET method defined to fetch a list of documents : http://localhost:70/DocumentRESTService.svc/GetDocuments/

Now I am trying to consume this service in my angular app and display the data . Following is the code : HTML :

<html>
    <script src="../../dist/js/angular/angular.min.js"></script>
    <script src="../../assets/js/one.js"></script>
    <body ng-app="myoneapp" ng-controller="oneAppCtrl">
                {{"Hello" + "AngularJS"}}
        <hr>
        <h1> Response from my REST Service </h1>
        {{hashValue}}

        <hr>
        <h1> Response from w3school REST Service </h1>
        {{names}}


    </body>
</html>

JS:

angular.module('myoneapp', [])
    .controller('oneAppCtrl', function($scope,$http){
        $scope.documentValue = {};

        $http({method: 'GET',
                url: 'http://localhost:70/DocumentRESTService.svc/GetDocuments/',
                headers:
                        {
//                          'Access-Control-Allow-Origin': 'http://localhost'
                        }                   
               })
            .success(function(data){ alert('Success!'); $scope.documentValue=data;})
            .error(function(data){ alert('Error!'); $scope.documentValue=data; alert('Error!' + $scope.documentValue);})
            .catch(function(data){ alert('Catch!'); $scope.documentValue= data;});

        $http.get("http://www.w3schools.com/angular/customers.php")
            .success(function(response) {$scope.names = response.records;});            
});

The strange behavior is this code works perfectly fine in IE11 , whereas it doesn't run in Chrome/Firefox.

Following is the response in the chrome:(for my REST service) , whereas the REST service from w3schools worked just fine.

{"data":null,"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":"http://localhost:70/DocumentRESTService.svc/GetDocuments/","headers":{"Accept":"application/json, text/plain, /"}},"statusText":""}

Console displayed following error message.

  • [Chrome Console:By opening from filesystem]

XMLHttpRequest cannot load http://localhost:70/DocumentRESTService.svc/GetDocuments/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'file://' is therefore not allowed access.

  • [Chrome Console:hosted using Brackets]

XMLHttpRequest cannot load http://localhost:70/DocumentRESTService.svc/GetDocuments/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:55969' is therefore not allowed access.

  • [Firefox Console:]

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:70/DocumentRESTService.svc/GetDocuments/. This can be fixed by moving the resource to the same domain or enabling CORS.

The question here are few:

  1. Why is localhost or my machineName considered to be a cross-domain request ? I am in the same domain , ain't I ?
  2. Are there any changes required to do at my service end to enable this behavior? If yes , where in WCF Service ?( based on something i read here )
  3. an JSONP be useful in this case ? If yes , how would i use it ? would it work with requests that need custom headers ?( NOt really sure what it is , but while resarching found a lot of answers mentioning this. reading links will be helpful. )

Any help or direction will be helpful.

P.S:

  • IDE:Brackets , if that matters .
  • AngularJS v1.4.3
  • I have referred various stackoverflow questions referring similar problem (CORS) , which involved $resource , $provider , $config , Also some related to deleting some header and adding some value one of the header. I am bit naive to this - any references to this will be helpful.
B Bhatnagar
  • 1,706
  • 4
  • 22
  • 35
  • 4
    a different port or subdomain is also consider cross domain by browser. Presumably your page is being opened on different port? How to implement CORS for any server environment is well documented all over the place ... simple web search. Also can't use `file://` protocol when opening your page. Not even CORS will help there – charlietfl Jul 24 '15 at 14:22
  • Your loading the page via a localhost url as well? (as opposed to file:// or 127.0.0.1) – Alex K. Jul 24 '15 at 14:24
  • For interest, IE does not care about port numbers for CORS -- so you can use that to test. Alternatively, start chrome with `chrome --args --disable-web-security` and it won't make the checks against CORS. – TZHX Jul 24 '15 at 14:26
  • @TZHX problem there is forgetting it's disabled and leaving a security hole on your machine. Enabling CORS is most ideal IMO – charlietfl Jul 24 '15 at 14:29
  • 1
    @charlietfl totally agree, for longer term -- but to just get started on stuff it can be useful to know the workarounds. – TZHX Jul 24 '15 at 14:30
  • Your response should have the 'Access-Control-Allow-Origin' header, not the request. So set your IIS to add that header to any responses your REST service sends out. – Shilly Jul 24 '15 at 14:30
  • @charlietfl : yes, you were right it was the problem due to different ports , my servie was on a different port and the client page on other. Thanks for that. Can you guide how shall i tackle the CORS problem now. – B Bhatnagar Jul 25 '15 at 09:41
  • @Shilly: Thanks for the suggestion , could you please explain how to add the response header in IIS? – B Bhatnagar Jul 25 '15 at 09:43
  • enable CORS headers. Topic is very very easy to research – charlietfl Jul 25 '15 at 12:13

3 Answers3

12

I struggled for way too long with CORS issues caused by the interaction of an emulated Ionic project (running locally) with some small Node.JS web services (also running locally).

Behold the short easy workaround : Chrome's plugin AllowControlAllowOrigin.

https://chrome.google.com/webstore/search/cross%20origin?utm_source=chrome-ntp-icon&_category=extensions

Just switch the radio button from red to green, and no more blocked request, error or warning ! Of course it's a temporary solution and you may have to put your hands in your request headers when the time to stop the local tests will come. In the meantime, that's a great way to avoid loosing time on those anoying recurrent issues.

Sendil.J
  • 131
  • 1
  • 8
  • This is by far the easiest solution I've come across. Specially when dealing with remote servers you don't have access to. – FernandoG Feb 01 '22 at 23:37
11

I could resolve this issue. Couple of ways to do so - I am jotting down all that i have tried and their references.

Answer to Ques1.

'Why is localhost or my machineName considered to be a cross-domain request?'

as @charlietfl mentioned and i Researched here: a different port or subdomain is also consider cross domain by browser.

Answer to Ques2.

'Are there any changes required to do at my service end to enable this behavior?'

YES! the change is required on server end itself. The server should respond to the request with

Access-Control-Allow-Origin: *

header. Here the * could be replaced with the request header itself or as per your application requirement. Excellent blog here explaining the workaround if you're using WCF REST Service. You need to add following line (headers) to each your service method to enable CORS in your service methods.

WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Methods", "POST"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Headers", "Content-Type, Accept");

A specification here is very helpful for enabling CORS on server / client.

Answer to Ques3.

JSONP mostly works for GET requests and aren't most advisable use ,rather enabling CORS is most recommended. (I haven't explored this area much but Wiki & stackoverflow article here were very descriptive).

Apart from that, for testing purpose, a nice chrome extension here can be helpful. It can be used to assure that the application has CORS issues.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
B Bhatnagar
  • 1,706
  • 4
  • 22
  • 35
  • so is this an answer to the question, or an attempt to answer the comments? – Claies Jul 25 '15 at 15:44
  • @Claies : mostly this can be considered as an answer but waiting for others to respond if anyone comes up correcting/adding to this understanding. – B Bhatnagar Jul 25 '15 at 16:25
  • After adding the header to the server endpoint, you may need to restart your back-end server. This caused me some time to figure out (Apache) – G M Jan 31 '23 at 02:42
3

If you are facing CORS issue in AngularJS applications while accessing REST API running in localhost machine check the following: Add the CORS Filter in your server application. In my case, I have added the below code in Spring application

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

In angularjs code, don't give URL like http://localhost:8080/../. Instead of localhost give your host IP number.

It will work properly

  • 1
    I was just having this issue with express and angular2, I didn't have to set Access-Control-* headers, I just changed the angular to point to 127.0.0.1:3000 and it cleared the problem up. Thank you! – toddmillernyc Mar 22 '17 at 02:43