42

I have searched over 200 sites(maybe exaggerating, but not by much) on how to be able to handle cors with angularjs. We have a local machine running a web API server. We are developing a client that calls on the API for data. When running the client from the server we receive data no problem. When we run it from a different domain we get a red 200 response when trying to fetch data and a blank response. Here is some code:

var myApp = angular.module('Project', ['ngResource']);

myApp.config(function($routeProvider){
    $routeProvider.
        when('/new', {templateUrl:'templates/new.html', controller:'EditProjectController'}).
        when('/mobile', {templateUrl:'templates/mobile.html', controller:'ProjectController'}).
        when('/it', {templateUrl:'templates/it.html', controller:'ProjectController'}).
        when('/writing', {templateUrl:'templates/writing.html', controller:'ProjectController'}).
        when('/all', { templateUrl: 'templates/all.html' }).
        when('/login', { templateUrl: 'partials/_login.html' }).
        otherwise({ redirectTo: '/all' });
});
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);



myApp.controller('ProjectController', 
function myApp($scope, $http, projectDataService, userLoginService) {
    $http.defaults.useXDomain = true;
    $scope.loadProject = function(){
        projectDataService.getProject(function(project){
            $scope.project = project;
            })


    };
    $scope.loadProject();
}

);

myApp.factory('projectDataService', function ($resource, $q) {
var resource = $resource('http://webapiserver/api/:id', { id: '@id' });
return {
    getProject: function () {
        var deferred = $q.defer();
        resource.query({ id: 'project' },
            function (project) {
                deferred.resolve(project);
            },
            function (response) {
                deferred.reject(response);
            });

        return deferred.promise;
    },
    save: function (project) {
        var deferred = $q.defer();
        project.id = 'project/9';
        resource.save(project,
            function (response) { deferred.resolve(response); },
            function (response) { deferred.reject(response); }
            );
        return deferred.promise;
    }
};
});

I have also tried this using $http but I get the same response (or lack thereof):

myApp.factory("projectDataService", function ($http) {

return {
    getProject: function (successcb) {
        $http.get("http://webapiserver/api/project").
        success(function (data, status, headers, config) {
            successcb(data);
        }).
        error(function (data, status, headers, config) {

    }
};
});

When I just browse to the url that is serving up the json in the browser it spits out the data. On the server we are allowing cross domain origins which is apparent by my previous statement. As you can see I am implementing the headers overrides in myApp.config I have even tried putting it directly in my controller... no difference...

3 days now on this task.

Help with this is MORE than appreciated. Thanks in advance.

Shane
  • 548
  • 1
  • 6
  • 17
  • So your GET request is failing? Please show the headers of the request and response. It will be easiest if you simply open up the network tab on Chrome and include everything in the headers section. – Ray Nicholus Jul 25 '13 at 03:29
  • Can you see the cross domain headers and the Options handshake happening if you review the XHRRequest in devtools in Chrome for instance – Si Robinson Jul 16 '14 at 09:35

4 Answers4

11

You may need to change your Web API a bit. I met the same kind of problem and wrote a post about how to fix this issue.

I used Sinatra for the API, I don't know what language you are using for your webservices but I guess you can apply it. Basically, you need to configure your server to accept CORS calls by defining which origins and which HTTP methods are allowed.

You said you already enable it on your server, but what did you do exactly ?

See this post for more details : CORS with angular.js

T_Dnzt
  • 244
  • 2
  • 8
  • If you're using Wildfly (JBOSS 8.X), I wrote a simple Java class called CorsFilter that adds some CORS headers to the response to a web service. The link to the example is at http://stackoverflow.com/questions/23346863/deployd-data-retrieved-via-angularjs-cors/23434583#23434583 all the way at the bottom. – javaauthority Feb 10 '15 at 06:41
  • 1
    The link to your personal blog appears to be broken. – mlhDev Jun 20 '15 at 02:22
2

If you are going to want to POST to your WebApi with data then you'll need to do a little more for Chrome to work. You'll need to intercept the preflight and include the clients origin as an allowed origin.

If there is a better solution for this then after many days working on this problem exclusively I couldn't find it. Finally, this is what worked for me.

Good luck...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

namespace MashupCoreApiApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }


        protected void Application_BeginRequest(object sender, EventArgs e)
        {

            if (Context.Request.Path.Contains("api/") && Context.Request.HttpMethod == "OPTIONS")
            {

                Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);
                Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST PUT, DELETE, OPTIONS");
                Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                Context.Response.End();
            }

        } 

    }
}
user3448990
  • 323
  • 6
  • 15
0

If it is ASP.NET WebAPI you need to install the CORS package and initialize CORS in the startup of the web server.

The package is called Microsoft.OWin.Cors

In the WebiApiConfig.cs put in something like:

var cors = new EnabledCorsAttribute("*", "*", "DataServiceVersion, MaxDataServiceVersion");
config.EnableCors(cors);
kamwo
  • 1,980
  • 1
  • 23
  • 32
pinnprophead
  • 215
  • 3
  • 14
0

You need to modify your Web API a little bit to handle the cross domain requests. Include the Microsoft Asp-Net Server Cors library in the Web Api project and few more code level modifications and you are ready to go. For more have a look here.

Your Angular part is totally fine.

Nitin Rawat
  • 209
  • 1
  • 5
  • 14