I have the following code, which was working fine until I deployed to a test server:
$scope.getUserList = function (userName) {
$http({
method: \
I would just make all URL relative.
url: "../GetUserList",
instead
url: "GetUserList",
Hard coding for the, <base href="/application_root/" />
dose not sound good idea to me as you might need to change this environment to environment, and has dependency over virtual directory name.
I would suggest defining a module that contains a global config that you can then pass around your application:
// Module specific configuration
angular.module('app.config')
.value('app.config', {
basePath: '/' // Set your base path here
});
Then you can access this from anywhere within your application thanks to AngularJS dependency injection:
// Make sure your config is included in your module
angular.module('app', ['app.config']);
// Access your config e.g. in a controller
angular.module('app')
.controller('TestCtrl', ['$scope','app.config', function($scope, config){
// Use config base path to assemble url
$scope.url = config.basePath + 'GetUserList';
...
}]);
Whenever the base path changes (e.g. when you change to another server or host), you just need to change it in your global config and you're done.
In the ng-init function pass a parameter that contains the value the virtual directory (int ASP.NET stored in Request.ApplicationPath).
<div ng-controller="ControllerName" ng-init="init('@Request.ApplicationPath')">
Inside the angular controller, use this value as prefix of URL in every http call. You can use this function to combine the paths
function combinePath(path1, path2) {
if (path1 == null) {
return path2;
}
var last = path1.slice(-1);
var first = path2.charAt(0);
if (last == '/' && first == '/') {
path1 = path1.substring(0, path1.length - 1);
}
return path1 + path2;
}
I'd suggest using an HTML base tag in the head, and coding all paths relative to this. In ASP.NET, for example, you can get a reference to the base of the application, which may or may not be the root path of the site, so using a base tag helps. Bonus: it works for every other asset too.
You can have a base path like this:
<base href="/application_root/" />
...and then links like "foo/bar.html" will actually be /application_root/foo/bar.html.
Another approach I like to use is to put named links in the header. I will often have an API root in one location and a directive template root somewhere else. In the head, I'll then add some tags like this:
<link id="linkApiRoot" href="/application_root/api/"/>
<link id="linkTemplateRoot" href="/application_root/Content/Templates/"/>
... and then use $provide in the module to get the link href and expose it to services and directives like so:
angular.module("app.services", [])
.config(["$provide", function ($provide) {
$provide.value("apiRoot", $("#linkApiRoot").attr("href"));
}]);
... and then inject it to a service like this:
angular.module("app.services").factory("myAdminSvc", ["apiRoot", function (apiRoot) {
var apiAdminRoot = apiRoot + "admin/";
...
Just my opinion though. Do the least complex thing for your application.
I wasn't able to use <base>
tag since my application was created in a popup dynamically from another origion. I was considering the others option in this thread to use something like a basePath variable and use it in every $http, ng-src, templateUrl
etc
But that was a bit overhead, built a interceptor that change every url before a xhr is made
var app = angular.module("myApp", []);
app.config(["$httpProvider", function($httpProvider) {
$httpProvider.interceptors.push('middleware');
}]);
app.factory('middleware', function() {
return {
request: function(config) {
// need more controlling when there is more than 1 domain involved
config.url = "//example.com/api/" + config.url
return config;
}
};
});
app.controller("Ctrl", ["$http", function($http) {
$http.get("books"); // actually requestUrl = http://example.com/api/books
}])
And html aswell
<div ng-include src="'view'">
<!-- actually src = http://example.com/api/view -->
</div>
But i do recommend to use <base>
tag instead unless you are using window.popup()
I had a similar problem I solve it with the just one line of code in my MVC page
<base href="~/" />