24

I have that simple code :

$http.get("/api/test")
    .success(function (data, status, headers, config) {
        console.log(data);
        return data;
    }).error(function (data, status, headers, config) {
        alert("error");
        return status;
});

It works fine, but the error function is never called, even when I return a 404 (Not Found) from the server... In that case it calls that 'success' function with status = 404...

Is that correct?

Thanks

Fiddler:

Request

GET http://localhost:41234/api/test HTTP/1.1
Host: localhost:41234
Connection: keep-alive
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko)    Chrome/25.0.1364.172 Safari/537.22
Referer: http://localhost:41234/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: ASP.NET_SessionId=bd1b3rib5j4beub0xbuhb1hm; FormsAuthentication=xxxxx

Response

HTTP/1.1 404 Not Found
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUGVzc29hxvY2FyLkFwaVxhcGcg==?=
X-Powered-By: ASP.NET
Content-Length: 0
0

5 Answers 5

30

I had the same problem and, honestly, follow the hints of this post put me in the wrong direction... so, I share my case/solution so other in my same situation could save time.

I'm using Angular.js 1.2.14 + WebApi 2. this my response for a NotFound status:

Cache-Control:no-cache
Content-Length:0
Date:Sat, 15 Mar 2014 14:28:35 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcU3ZpbHVwcG9EaXNjaXR1clxhcGlcTWFnMTRcYXBpXGxlc3Nvblw4NA==?=

As you can see, Content-Lenght:0, but that's ok.

My problem was the uncorrect use of Angular.js interceptor, in particular something like this:

responseError: function (result) {
                // check something 
                return result;
            }

returning result without throw an exception or rejecting the promises (as written in docs) makes Angular believe that I want to convert rejection in correct resolution and, after that, success callback is called.

I correct my code as follow:

responseError: function (result) {                    
                // check something 
                return $q.reject(result);
            }
Sign up to request clarification or add additional context in comments.

1 Comment

Same in my case. This is more useful than the selected answer.
5

The problem is your webserver, it is setting content-length to 0 that means that is a valid value as you can see on HTTP/1.1 specification.

Also I made a example on JSFiddle showing the error and success examples. See here.

The headers from the error example:

Request:

GET /error/ HTTP/1.1
Host: fiddle.jshell.net
Connection: keep-alive
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like  Gecko) Chrome/26.0.1410.65 Safari/537.31
DNT: 1
Referer: http://fiddle.jshell.net/danielcsgomes/cAMc6/1/show/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: UTF-8,*;q=0.5
Cookie: csrftoken=4tNVNxC5v6BSq9yJCKkHlGFJBz3cClqd`

Response:

HTTP/1.1 404 NOT FOUND
Server: nginx/0.8.54
Date: Fri, 12 Apr 2013 00:38:07 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Cookie
Content-Encoding: gzip

2 Comments

This is incorrect. Angularjs doesn't care what the content-length is.
This answer should not be marked as right, it's actually wrong like AgDude mentioned. For me the right answer was the one from @wilver (see below)!
3

If you are using AngularJS version 1.1.1 or greater...

Does appending '.json' work?:

$http.get("/api/test.json")
  .success(function (data, status, headers, config) {
      console.log(data);
      return data;
  }).error(function (data, status, headers, config) {
      alert("error");
      return status;
});

If so, it can also be fixed with:

myModule.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}]);

See this => Angular JS Fails After Upgrade from 1.1.0 to 1.1.1

3 Comments

Hello, appending .json is generating that error: {"message":"No HTTP resource was found that matches the request URI 'localhost:4021/api/… type was found that matches the controller named 'user.json'."} ... I´m using .NET Web API on server...
I added the fiddler request/response to question
why would changing the extension help in this particular situation... I don't see it
2

Maybe a little on late but... At the moment Angular $http request give you a premise so you can change it to:

$http({
    method: "yourMethod",
    url: "yourUrl",
    data: {yourDataObj}
}).then(function (res) {     //first function "success"
    console.log(res.data);
}, function (err) {          //second function "error"
    console.log(err);
});

Comments

0

We moved the post to a factory, we don't really care here about testing the $http stuff, just what it does on success or error:

factoryModule.factory('GiftFactory', function ($http, Settings) {
    var saveUrl = Settings.endpoints.saveUrl;

    return {
        createGift: function (data) {
            var gift = { gift: JSON.stringify(angular.toJson(data.gift)) };
            return $http.post(saveUrl, gift);
        }
    };
});

We call it like this:

    $scope.submit = function () {
        $scope.submitting = true;
        GiftFactory.createGift($scope)
            .success(function () {
                $window.location = Giving.endpoints.indexUrl;
            }).error(function() {
                $scope.submitting = false;
                alert('an error occurred');
        });
    };

We test it like this:

describe('donation controller', function () {
var $scope, q, window, controller;

beforeEach(module('giving.donation'));
beforeEach(inject(function ($controller, $rootScope, $q) {
    $scope = $rootScope.$new();
    window = {};
    q = $q;
    giftFactory = {};
    controller = $controller('DonationController', { $scope: $scope, $window: window, GiftFactory: giftFactory });
}));

describe('submit', function () {
    var deferred;
    beforeEach(function () {
        deferred = q.defer();

        deferred.promise.success = function (fn) {
            deferred.promise.then(
                function (response) {
                    fn(response.data, response.status, response.headers);
                });
            return deferred.promise;
        };
        deferred.promise.error = function (fn) {
            deferred.promise.then(null,
                function (response) {
                    fn(response.data, response.status, response.headers);
                });
            return deferred.promise;
        };
    });

    it('should redirect on success', function () {
        //Arrange
        Giving = { endpoints: { indexUrl: "/testurl" } };

        giftFactory.createGift = function () {
            return deferred.promise;
        };

        //Act
        $scope.submit();

        deferred.resolve({});
        $scope.$apply();

        //Assert
        expect($scope.submitting).toBeTruthy();
        expect(window.location).toBe('/testurl');
    });

    it('should set submitting back to false on error', function () {
        //Arrange
        Giving = { endpoints: { indexUrl: "/testurl" } };

        giftFactory.createGift = function () {
            return deferred.promise;
        };

        //Act
        $scope.submit();

        deferred.reject({});
        $scope.$apply();

        //Assert
        expect($scope.submitting).toBeFalsy();
        expect(window.location).toBeUndefined();
    });
});

});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.