Using Angular.JS with ASP.NET AJAX libraries to call WCF REST services

WCF has enabled building of REST services via the WebGet and WebInvoke attributes and the WebHttpBinding. This makes it easy to expose a ServiceContract as a REST service. Consuming this service from JavaScript is not too difficult and you can use jQuery, Angular.JS etc. to make it easier. But when you have to access many services in this way you want to be able to use the generated JavaScript proxy (available at the https://machine/service/service.svc/js endpoint of the WCF REST service). The nice part about this proxy is that it preserves the namespace of your service and gives a nice object-oriented way of calling the service like so:

 var proxy = new tempuri.org.IService();
proxy.GetDataREST(id, successRESTService, errorRESTService, null);             

The problem with this proxy is that it has a dependency on the ASP.NET ScriptManager server controls so you generally have to include it within an ASPX page. However in the day of HTML+JS apps you can use this with a plain HTML file if you know which JS library to include from the ASP.NET CDN:

 <script src="https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>

This will include the compressed and obfuscated ASP.NET JS library that has the helper functions required to use the generated service proxy. Now recently I’ve gotten to love Angular.JS and I thought of using that framework to write a tiny HTML app that calls a WCF REST service using the generated proxy. Off course it generally works fine with one big problem. The callbacks used by the ASP.NET AJAX libraries (successRESTService and errorRESTService in the example above) don’t seem to work the same way as the Promises used by Angular.JS. As a result, although the callback is invoked correctly, none of the bindings are updated during the callback. So the view elements do not show the data returned form the web service. However, I was able to force the view to update by calling $scope.$digest(); at the end of the callback method. So the completed app looks like so:

 <!doctype html>
<html ng-app>
<head>
    <title>Call REST service via Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
    <script src="https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
    <script src="https://localhost/RESTJSONCompare/Service.svc/js"></script>
    <script type="text/javascript">
        var ServiceController = function ($scope, $http) {
            var id = 123;
            $scope.getPerson = function () {
                var proxy = new tempuri.org.IService();
                proxy.GetDataREST(id, successRESTService, errorRESTService, null);               
                $scope.ErrorMessage = "";
            }
            var successRESTService = function (data) {
                $scope.PersonID = data.ID;
                $scope.PersonName = data.Name;
                $scope.PersonAddress = data.Address;
                $scope.$digest();
            }
            var errorRESTService = function (data) {
                $scope.ErrorMessage = "HTTP error code : " + data;
                $scope.$digest();
            }
        };
    </script>
</head>
<body>
    <div ng-controller="ServiceController">
        <input type="button" ng-click="getPerson();" value="Call REST Service">
        <hr />
        <ul>
            <li>
                ID: {{PersonID}}
            </li>
            <li>
                Name: {{PersonName}}
            </li>
            <li>
                Address: {{PersonAddress}}
            </li>
        </ul>
        <label>{{ErrorMessage}}</label>
    </div>
</body>
</html>

This gives you the best of both worlds, the power of Angular.JS data binding and the simplicity of the ASP.NET AJAX proxies + WCF REST services.

By popular demand, I have also uploaded the WCF service to this post.

RESTJSONCompare.zip