I'm trying to get my first ASP.NET Webforms and AngularJS app up and running, but I'm struggling...
I created a blank, new ASP.NET 4.5.1 webforms app, and included WebAPI into the mix. I created a sample page for my list of customers, and a standard, EF6-based WebAPI CustomerController : ApiController
with all the usual CRUD methods. I tested that WebAPI using Fiddler and low and behold - I get my 8 customers back from my database.
Getting this into AngularJS however has been a bit of a unsuccessful and highly frustrating experience ....
I included AngularJS
from NuGet and that seems to have worked - no errors shown or anything, a pile of angular*.js
files dumped into my Scripts
folder.
I created a basic CustomerList.aspx
page based on a master page which includes the <html lang="en" ng-app="TestAngular">
tag.
In order to get the data from the WebAPI service, I created my Angular module, and created a model
inside the $scope
, and created a service to fetch the data from the WebAPI:
Inside app.js
:
var testModule = angular.module('TestAngular', [ ]);
testModule.controller('clientController', function ($scope, clientService) {
$scope.model = [];
clientService.getAllClients(function(results) {
$scope.model.clients = results;
});
$scope.model.clientCount = $scope.model.clients.count;
});
testModule.factory('clientService', function ($http) {
var srv = {};
srv._baseUrl = 'http://localhost:56313';
// Public API
return {
getAllClients: function(callback) {
return $http.get(srv._baseUrl + '/api/Customer').success(callback);
}
};
});
From what limited Javascript understanding I have, this should define a clientService
(the testModule.factory()
call) that calls my WebAPI URL, gets the JSON back, and the callback function then stuffs those customers retrieved into the $scope.model.clients
property, and the $scope.model.clientCount
should also be calculated.
My ASPX page looks something like this:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CustomerList.aspx.cs" Inherits="TestAngular.CustomerList" MasterPageFile="~/Site.Master" %>
<asp:Content runat="server" ID="content" ContentPlaceHolderID="MainContent">
<h2>My customers</h2>
<div class="panel panel-default" data-ng-controller="clientController">
We have a total of {{ model.clientCount }} clients in our database table ...
<div class="list-group" data-ng-repeat="client in model.clients">
<div class="list-group-item">
<span>{{ client.Name }}</span><br/>
<span>{{ client.Name2 }}</span><br/>
</div>
</div>
</div>
</asp:Content>
So the <div>
with the data-ng-controller
should "connect" that DIV with the AngularJS controller, should load the customers from the WebAPI call, and contain them in the model, which would then be rendered to the ASPX page using the data binding syntax ({{ client.Name }}
etc.)
Trouble is: the call to the WebAPI happens and the correct 8 customers are returned, however, when I debug into the Javascript code, the clientCount
is always undefined
and the ASPX page only shows two empty rows which probably would correspond to customers that have been retrieved - but why only 2, not 8 ??
I'm totally lost and stuck - can anyone spot what I'm doing wrong, what I'm missing here??
You are definately on the right track. At the moment, the problem is down to the clientService
getAllClients
method.
You should return
the promise and then the data will chain through to the controller:
getAllClients: function(callback) {
return $http.get(srv._baseUrl + '/api/Customer').success(callback);
}
You may also want to take a look at the count line:
$scope.model.clientCount = $scope.model.clients.count;
Before the promise is resolved (and the callback is invoked), $scope.model.clients
will be undefined
. So, I'd expect this line to fail. Also, to get the count of an array, you need length
.
You should set the clientCount
inside of the callback:
clientService.getAllClients(function(results) {
$scope.model.clients = results;
$scope.model.clientCount = $scope.model.clients.length;
});
Edit:
Typically, it is favoured to use the promise returned by $http
. So, the controller would slightly change to:
clientService.getAllClients().then(function(response) {
$scope.model.clients = response.results;
$scope.model.clientCount = response.results.length;
});
And then the service would change to:
getAllClients: function() {
return $http.get(srv._baseUrl + '/api/Customer');
}
Angular uses promises from $q instead of callbacks (for most apis). They make chaining and exception handling much easier.
Also, since, in this case, you know you are handling a promise from $http
, you can use the success
method in the controller as well:
clientService.getAllClients().success(function(results) {
$scope.model.clients = results;
$scope.model.clientCount = results.length;
});
success
unwraps the response and sends only the body through to the callback.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With