0

I have a website that uses the angularBootstrapNavTree control. It works fine for me on my local machine. On my server, I installed Visual Studio ( it's MVC5 ) and debugged an error that occurred on the server but not locally with serialisation. Now, when I go to my URL of my WebAPI2 service, my data is returned. If I browse to the page with this script ( in a .js file ):

var app, deps;

deps = ['angularBootstrapNavTree'];

if (angular.version.full.indexOf("1.2") >= 0)
{
    deps.push('ngAnimate');
}

app = angular.module('PVU', deps);

app.controller('PVUController', function ($scope, $timeout, $http, $window)
{
    $scope.doing_async = true;

    $scope.data = null;

    $http({ method: 'GET', url: '/Products/GetProducts/' }).
    success(function (data, status, headers, config)
    {
        $scope.doing_async = false;
        return $scope.my_data = data;
    }).
    error(function (data, status, headers, config)
    {
    });

    $scope.clickhandler = function (branch)
    {
        $scope.thedata = branch.data;
        $scope.$apply();
    };

    treedata_avm = [
      {
          label: 'Loading'
      }
    ];


    $scope.my_data = treedata_avm;
});

The page runs, and the tree shows 'loading'. If I set a breakpoint, the success function is called and my data is there. But, from the moment the controller callback is called ( $scope.doing_async = true; ), this error is on my console:

Error: [$injector:unpr] http://errors.angularjs.org/1.2.14/$injector/unpr?p0=nProvider%20%3C-%20n%20%3C-%20abnTreeDirective
    at Error (native)
    at http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:6542
    at http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:19418
    at Object.i [as get] (http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:18494)
    at http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:19493
    at i (http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:18494)
    at Object.r [as invoke] (http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:18706)
    at http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:23593
    at Array.forEach (native)
    at r (http://67.214.99.130/bundles/angular?v=RhmTtQ27BhbKD8lYJqRRXD93x9Dmqd7oWtir-Op3k8k1:1:6870) 

I thought I had the non minified version of Angular installed, but the error shows up at the start of the file, all on one line and unreadable. The link goes to a page that says a module is not defined, but I checked, and all the $xxx objects are valid inside the method, and I don't know that I define anything else...

I am not sure if it's an IIS issue, because everything is working inside Visual Studio, but this is my last deployment task, so I appreciate any help or advice.

Thanks

cgraus
  • 784
  • 2
  • 9
  • 26
  • Are you uglifying your own code ? – Jscti Apr 10 '14 at 11:46
  • @Bixi That is exactly what is going on, Microsoft's System.Web.Optimization library creates "bundles" which concatenates files and minifies/uglifies them. – Brocco Apr 10 '14 at 20:42
  • Then see Brocco answer, it's a common dependency injection problem. – Jscti Apr 10 '14 at 20:44
  • possible duplicate of [Angular "Unknown Provider" error after minification with Grunt Build in Yeoman app](http://stackoverflow.com/questions/20340644/angular-unknown-provider-error-after-minification-with-grunt-build-in-yeoman-a) – Jscti Apr 10 '14 at 20:45
  • http://stackoverflow.com/questions/22676454/angularjs-not-working-in-release-mode-minified/ – j.wittwer Apr 10 '14 at 21:25
  • Thanks for the links, guys, it certainly looks similar. I have not changed the debug setting, unless doing a 'Publish' did that without me realising ( I'll check that tonight ). I have other angular pages which work, so now I know that this is an issue, I'll read up and compare the differences. I do have a question - the code I posted, looks like that in chrome. If it had been minified, wouldn't I see the mangled code, in chrome ? – cgraus Apr 10 '14 at 22:44

2 Answers2

1

Angular handles its DI via string matching, so you will need to change this:

app.controller('PVUController', function ($scope, $timeout, $http, $window)

to this:

app.controller('PVUController', 
    ['$scope', '$timeout', '$http', '$window', 
    function ($scope, $timeout, $http, $window){
}]);

When the application is compiled with debug=false in web.config the bundles that are created are concatenated together and minified. The concatenation is not an issue, but the minification (uglify) process renames the parameters and the string array notation is how Angular reconciles the dependencies because as strings the minification process will ignore them allowing the dependencies to be resolved correctly.

Brocco
  • 62,737
  • 12
  • 70
  • 76
  • Thanks, but I did that: app.controller('PVUController', (['$scope', '$timeout', '$http', '$window', function($scope, $timeout, $http, $window) { The errors are still the same.... Thanks – cgraus Apr 10 '14 at 21:22
  • I noticed I'd added a bracket, but removing it did not help. It loads and runs, it gets the data, but it never shows, it's like the array of data was empty. I get a line where the tree nodes should be. – cgraus Apr 10 '14 at 21:24
  • Have you confirmed that your web server is actually sending out data via tool like fiddler or postman? – Brocco Apr 11 '14 at 02:21
  • What I actually did was, after the application was logged in, went to the URL that serves the data and looked at it in the browser. The callback in my code also calls the 'success' method and I set a breakpoint in there ( and one in the error, where I expected it to go ) and looked at the data and confirmed that it was what I expected it to be. So I've not used Fiddler, I've looked at it two ways in Chrome and it looks fine to me. – cgraus Apr 11 '14 at 03:18
  • That's legitimate IMO. I'm not sure if it would cause an issue, but you don't need this return `return $scope.my_data = data;` just set $scope.my_data = data; – Brocco Apr 11 '14 at 03:27
  • OK - I am at work now, and I admit that this was the first Angular code I ever wrote, so thanks for that tip, I did it that way based on an example. I'll make that change, even if it doesn't fix this issue, I'd like to learn how to do this better. So I'll try that locally, and I'm going to try turning debug on, on the server, not as a solution, but to work out if that's the issue. – cgraus Apr 11 '14 at 06:10
  • Sure enough, I set debug = 'true' in the web.config and it seems to be working, so that proves you're right. I needed it to work for a demo, so I'll leave it like this, then dig in and work out how to fix it. Thanks for the help !! – cgraus Apr 11 '14 at 21:45
0

OK - I got to the bottom of this. Brocco's answer was what got me on the right path, but, my js files were not being bundled and thus not being minified. The issue was that the angular-tree control must have code INSIDE it, that does not survive this process. That's why everything else worked, it was when it tried to step in to the tree code, that it failed ,because that's what was broken. So, I moved the tree out of my bundles and just included it directly, and everything works now. So, if you're using this control:

https://github.com/eu81273/angular.treeview

and you're using MVC5 and searching for the solution to this issue, that's what it is. Take it out of your bundles and just include it inside your scripts, so that it doesn't get bundled and it will work fine.

cgraus
  • 784
  • 2
  • 9
  • 26