Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

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??

share|improve this question
up vote 3 down vote accepted

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.

share|improve this answer
    
Thanks - tried this - still don't see anything useful on screen :-( It's still the same as before.... – marc_s Mar 5 '15 at 13:56
    
I just realized that you are using a callback instead of a promise mechanism. I'll edit the answer to show what is typically done. – Davin Tryon Mar 5 '15 at 13:59
    
OK, now I'm seeing data - but the clientCount still seems to be undefined.... – marc_s Mar 5 '15 at 14:01
    
Sorry, I think you want model.clients.length instead. – Davin Tryon Mar 5 '15 at 14:02
    
@DavinTryon, I would have avoided using .success - it is an $http-only function and not per-promise-spec. Also, any .then inside getAllClients would break this usage. Also, I'd wager that the callback approach would have worked had there been a $scope.$apply in the callback function, but promises is definitely the way to go. – New Dev Mar 5 '15 at 14:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.