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.
Comments
Anonymous
January 16, 2014
Thank you very much for this solution! It was really helpful!Anonymous
January 16, 2014
Awesome! Thanks Sujit!Anonymous
March 05, 2014
Nice article.. But I have found another simple example to call a WCF RestFul Service using jQuery AJAX Call, please refer to link below:- www.etechpulse.com/.../how-to-consume-wcf-restful-service-in.htmlAnonymous
May 13, 2014
Please also show how we can create "RESTJSONCompare/Service.svc/js"Anonymous
May 13, 2014
You don't have to create the /js endpoint. It is automatically created by WCF via the WebHttpBinding. See msdn.microsoft.com/.../bb412178(v=vs.110).aspx for a sample.Anonymous
August 18, 2014
Please show the corresponding WCF service so that we can easily understand...Anonymous
August 18, 2014
I tried to call WCF service by way u mentioned in ur code. But I couldn't be able to get my server data. Plz post ur corresponding web service and whats the use of 123 in Controller CodeAnonymous
August 18, 2014
The 123 is just the input parameter (record ID) to the REST service. I will post the service shortly. Use the IE11 F12 tools to determine what is happening between your JS code and the service.Anonymous
August 19, 2014
Hi Sujit I am not running my WCF by iis but local vs server. And I still didn't get any response by server. So can u tell step by step so I can get wht I m doing wrong. Thanks in advance :)Anonymous
August 19, 2014
Shivani, you mean the WCF service is running on IIS Express? (http://localhost:<some random port>)Anonymous
August 21, 2014
I meant so.Anonymous
November 11, 2014
The better Angular way to do this is to use $scope.$apply(). $scope.$apply(function() { $scope.PersonID = data.ID; $scope.PersonName = data.Name; $scope.PersonAddress = data.Address; }); $scope.$apply will call $scope.$digest() when it is done, but it handles errors better. ShawnAnonymous
June 18, 2015
This works very nicely. Does this technique work for cross-domain scenarios as well?Anonymous
November 28, 2015
HEY, where is the java script file in the downloaded file.Anonymous
November 30, 2015
It is dynamically generated when you access http://localhost/RESTJSONCompare/Service.svc/js