10

My post method is something like this:

    public HttpResponseMessage AddUser(User user)
    {
        UserManager userManager = new UserManager();
        try
        {
            userManager.Create(user);

            var savedUser = userManager.FindUserByClientId(user.ClientId);
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = savedUser.Id }));
            return response;
        }
        catch(Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
        }

    }

In angular, I am trying to read that Location header but so far I'm still not able to.

return $http.post('http://localhost:30028/api/values/adduser', user)
        .success(function (data, status, headers, config) {
            alert(angular.toJson(data));
            alert(angular.toJson(status));
            alert(angular.toJson(headers));
            alert(angular.toJson(config));
         };

I am just checking out the contents of each of those and none has the location header. Is there a way in angular to access the location header so that i know the url of my new object?

raberana
  • 11,739
  • 18
  • 69
  • 95

2 Answers2

20

According to the documentation, the headers object is actually a function that returns the header, like so:

.success(function(data, status, headers, config) {
    alert( headers('Location') );
});

If you want a collection of all headers, you can do this:

.success(function(data, status, headers, config) {
    console.log( headers() );
});

Note: If your server sets a response code of 301 or 302, you will not be able to get the Location header, as it will be automatically and transparently followed by the XMLHttpRequest object.

So, make sure you are correctly setting the response code. I was testing this in PHP (which I don't use as much), and had forgotten that setting a Location header automatically set the response code. To test this, I had to use:

header('Location: blah-blah', true, 200);

Here's my working code sample, just save it to location-test.php on a PHP server and run it:

<?php

if(isset($_GET['q'])) {
    header('Content-Type: application/json');
    header('Location: user/1', true, 200);
    echo json_encode(array('query' => $_GET['q']));
} else {

?>
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">

  <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.5/angular.min.js'></script>
  <script type='text/javascript'>//<![CDATA[ 

angular.module('myApp', [])
.controller("myController", function($scope, $http) {
    $scope.loc = "Loading...";
    $http.get('location.php?q=hello')
        .success(function (data, status, header, config) {
            console.log(header());
            $scope.loc = header('Location');
         })
        .error(function(data, status) {
            console.log((data || 'Req Failed') + ': ' + status);
        });
});
  //]]></script>

</head>
<body>
    <div ng-app="myApp" ng-controller="myController">
        Location Header: {{loc}}
    </div>
</body>
</html>

<?php

}
OverZealous
  • 39,252
  • 15
  • 98
  • 100
2

Since .success() is deprecated in $http and has been replaced with .then() the update to this answer is to call header directly on the response that is injected into the promise.

$http.post('http://localhost:30028/api/values/adduser', user)
    .then(function (response) {
        alert(angular.toJson(response.headers));
        //or
        alert(response.headers('Location'));
 });
JTG
  • 8,587
  • 6
  • 31
  • 38