We will use Visual Studio 2008 and .Net 3.5 framework. To make it simpler as possible we will not use web api, just plain old .net services.
First let's create the .net part. Open up Visual Studio and create a 'New Web Site...'(shift+alt+N), for the type of the web site choose 'ASP.NET Web Service', in the name put what you want, and in the language choose 'Visual C#'. Click the OK button. Go to 'Solution Explorer' and double-click on the 'App_Code\Service.cs' file. First let's create a class for holding the clients:
public class client { public string name { get; set; } public string company { get; set; } public client() { } public client(string name, string company) { this.name = name; this.company = company; } }Then we will create the method that exposes the clients:
[WebMethod()] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public Listyou should also uncomment the line:getData() { List clients = new List (); clients.Add(new client("Philip J. Fry","Planet Express")); clients.Add(new client("Homer J. Simpson", "Nasa")); return clients; }
\\ [System.Web.Script.Services.ScriptService]In web.config add the following inside the /<system.web/>:
<webServices> <protocols> <add name="HttpGet"/> <add name="HttpPost"/> </protocols> </webServices>The .Net part is done. You can now start the service (CTRL+F5). In the top of the page you'll have the two available methods, click on getData and then on 'invoke' and copy the given url.
angular.module('aspNetWebserviceApp',[]);In the controllers folder, you can delete all the content from controller.js and put the following code:
"use strict"; var myControllers = angular.module('aspNetWebserviceApp.controllers',[]);Go back to the app.js and inject the controller dependency:
angular.module('aspNetWebserviceApp',['aspNetWebserviceApp.controllers']);Now all of your controllers are in one place, and accessible throughout the app. To access the web service we use a service. In angular you'll have the following service options:
"use strict"; var myServices = angular.module('aspNetWebserviceApp.services',[]); myServices.service('clientsService', function ($http, $q) { this.getClients = function () { var deferred = $q.defer(); $http({ data:{}, method:'GET', headers:{ 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/json; charset=utf-8' }, url:'http://localhost:58116/clients/Service.asmx/getData' }) .success(function (data, status, headers, config) { deferred.resolve(data.d); }) .error(function (data, status) { deferred.reject("Error: "+data.d); }); return deferred.promise; } });In the line
myServices.service('clientsService', function ($http, $q) {we inject two dependencies, $http and $q:
- $http - a service designed to access remote HTTP servers via XMLHttpRequest or JSONP. (very similar to $jQuery's $.ajax() method)
- $q - Implements promises.
this.getClients = function(){we start by creating a defer object which hold up the result of the call, in the form of a promise, either a success or a failure.
var deferred = $q.defer();then we connect to the web service by using:
$http({ data:{}, method:'GET', headers:{ 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/json; charset=utf-8' }, url:'http://localhost:58116/clients/Service.asmx/getData' });If you used the $.ajax jQuery method you'll notice the similarities. Since we're only retrieving data, the 'data' parameter is empty, also for the same reason, the 'method' parameter will be 'GET', and in the header we specify that the response will be in JSON format. Lastly we put the webserver url(Did you save it?) in the 'url' parameter. And that's it. After that we must, based on the data retrieved, fill the deferred object.
.success(function (data, status, headers, config) { deferred.resolve(data.d); }) .error(function (data, status) { deferred.reject("Error: "+data.d); });and return it:
return deferred.promise;the service part is done. Now let's get back to the app.js and inject the services dependency:
angular.module('aspNetWebserviceApp', ['aspNetWebserviceApp.controllers','aspNetWebserviceApp.services']);In the controllers js file, inject the service:
myControllers.controller('mainCtrl',function ($scope,clientsService)and create an empty container for the clients data:
$scope.clients = [];then we fill this array:
$scope.getClients = function () { clientsService.getClients() .then(function (data) { $scope.clients = data; }) }In this method we call the getClients() from the service we previously created and, in case of success, assign the income to the clients array. If you want, you can load up the data when the page loads by creating the following function in the controller:
$scope.init=function(){ this.getClients(); }In your index.html file remember to link to the services file: (if you're using webstorm type 'script:src' tab and copy the path to the js file)
<script type="text/javascript" src="scripts/services/aspNetService.js"></script>Then erase html markup inside (leave the script tags) and create the following
:
<div ng-cloak="" ng-controller="mainCtrl" ng-init="init()"> <table class="table table-stripped"> <tr> <th>Name</th> <th>company</th> </tr> <tr ng-repeat="client in clients"> <td>{{client.name}}</td> <td>{{client.company}}</td> </tr> </table> </div>The ng-controller="mainCtrl" is to indicate that the data inside the div will come from the "mainCtrl" controller, the ng-init="init()" calls the preload function we created, and ng-cloak="" hides those ugly {{ }} from view, displaying only the data when it is in his final state. Then we create a table to show the data from the controller.
<tr ng-repeat="client in clients"> <td>{{client.name}}</td> <td>{{client.company}}</td> </tr>These lines show another cool feature in AngularJS, the ng-repeat directive. Basically, it iterates through clients collection and for each one of the clients creates a table row with two columns, name and company of the client. Probably, the data will not show up and that because of the following error (this was on Chrome):
XMLHttpRequest cannot load http://localhost:58116/clients/Service.asmx/getData. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.
This is because we are accessing another server in the same host. To solve this in Chrome you can do the following. Go to Task Manager and close every instance of Chrome. Then, create a shortcut to chrome on the desktop and set the target to: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security Now, start this Chrome and load the webservice and the angular app. And you'll see that the data will load up quite nicely.