AngularJS calls $http.get constantly from html template, but not from within controller?

AngularJS keeps calling the http get request over and over again!!

If I call getContexts directly in the controller it's fine... but if I call it from the html template, it just keeps calling the get.

Partial contextCtrl.js:

            'use strict';

            app.controller('ContextCtrl', function ContextCtrl($scope, $location, $http, $rootScope, ContextService) {  
                $scope.getContexts = function(keys)
                {
                    $scope.contexts = {};
                    $http.get('/getContextsWS?keys=' + keys).
                    success(function(data){
                      $scope.contexts = data;
                    });
                }

                // This works
                $scope.getContexts('["context::one", "context::two"]')
            });

Partial html section:

            <section id="contextSection" ng-controller="ContextCtrl">

                // This causes get to keep calling!
                {{getContexts('["context::one", "context::two"]')}}

                // Just checking
                {{contexts|json}}

                <nav>
                    <ul ng-show="contexts.length" ng-cloak>
                        <li ng-repeat="context in contexts">
                            <div class="view" ng-click="contextSelected(context)">{{context.name}}</div>
                        </li>
                    </ul>
                </nav>
            </section>

This is driving me nuts!

Okay I've tried your hidden field example and I can't seem to get it to work, but perhaps I'm missing something...

The html:

            <section id="contextSection" ng-controller="ContextCtrl">
            <input type="hidden" ng-model="contextIds" copy-to-model value='@product.item.contextIds'/>

The directive:

            mto.directive('copyToModel', function ($parse) {
                return function (scope, element, attrs) {
                    $parse(attrs.ngModel).assign(scope, attrs.value);
                }
            });

The controller:

            app.controller('ContextCtrl', function ContextCtrl($scope, $location, $http, $rootScope, ContextService) {  

                // I can read this, but it never changes, and without this the contextIds in the alert are null
                $scope.contextIds = "...";

                $rootScope.alert = function(text)
                {
                    alert(text);
                }

                $rootScope.alert("$scope.contextIds: " + $scope.contextIds);

            });

Any idea what am I doing wrong?

The expressions inside your {{ }} binding code will be re-evaluated anytime Angular notices that something in the model has changed (I've oversimplified what actually occurs). If you want to call getContexts just once don't put it inside {{ }} in your markup and just call it in your controller code.

Basically assume that code inside {{ }} can and will get called multiple times..

So try removing:

// This causes get to keep calling!
{{getContexts('["context::one", "context::two"]')}}

And rely on your controller code (though you might not want getContexts in your scope if you don't call it from your markup):

// This works
$scope.getContexts('["context::one", "context::two"]')