在AngularJS中使用相对path进行服务调用

我有下面的代码,这工作正常,直到我部署到testing服务器:

$scope.getUserList = function (userName) { $http({ method: "get", url: "GetUserList", params: { userName: userName } }). success(function (data) { $scope.users = data; }). error(function () { alert("Error getting users."); 

问题是我部署到一个虚拟目录,并且下面的调用尝试从服务器根打到GetUserList。 这是有道理的,我知道有很多方法可以解决这个问题。

我想知道的是在Angular中以便携和可维护的方式引用服务URL的正确方法。

我build议在头部使用HTML基本标签,并编码所有相关的path。 例如,在ASP.NET中,您可以获得对应用程序基础的引用,该引用可能是也可能不是该网站的根path,因此使用基本标记会有所帮助。 奖金:它也适用于其他资产。

你可以有这样的基本path:

 <base href="/application_root/" /> 

然后像“foo / bar.html”这样的链接实际上就是/application_root/foo/bar.html。

我喜欢使用的另一种方法是将名为链接的标题。 我经常在一个位置有一个API根,在其他位置有一个指令模板根。 在头上,我会添加一些这样的标签:

 <link id="linkApiRoot" href="/application_root/api/"/> <link id="linkTemplateRoot" href="/application_root/Content/Templates/"/> 

…然后在模块中使用$ provide来获得链接href并将其暴露给服务和指令,如下所示:

 angular.module("app.services", []) .config(["$provide", function ($provide) { $provide.value("apiRoot", $("#linkApiRoot").attr("href")); }]); 

…然后将其注入到像这样的服务:

 angular.module("app.services").factory("myAdminSvc", ["apiRoot", function (apiRoot) { var apiAdminRoot = apiRoot + "admin/"; ... 

只是我的意见。 为你的应用程序做最简单的事情。

我会build议定义一个包含全局configuration的模块,然后你可以传递你的应用程序:

 // Module specific configuration angular.module('app.config') .value('app.config', { basePath: '/' // Set your base path here }); 

那么你可以从你的应用程序的任何地方通过AngularJSdependency injection来访问它:

 // Make sure your config is included in your module angular.module('app', ['app.config']); // Access your config eg 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'; ... }]); 

每当基本path改变时(例如,当你改变到另一台服务器或主机),你只需要改变你的全局configuration,你就完成了。

我无法使用<base>标记,因为我的应用程序是从另一个原点dynamic创build的。 我正在考虑这个线程中的其他选项使用类似basePathvariables的东西,并在每个$http, ng-src, templateUrl等中使用它

但是,这是一个开销,build立一个拦截器,改变每一个url在xhr之前

 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 }]) 

和html也

 <div ng-include src="'view'"> <!-- actually src = http://example.com/api/view --> </div> 

但是我build议使用<base>标记,除非你使用window.popup()

使用$位置服务 – 它会返回你的path,散列,服务器地址..你需要的一切! 你的调用将是$location.path()+"/GetUserList"或类似的东西。

看到这里: http : //docs.angularjs.org/guide/dev_guide.services.$location

接受的答案帮助了我。 我正在使用Angular提供了我的一个MVC应用程序。 我采取了一个额外的步骤,以便我的baseUrl可以在我的angular度控制器内用于web api调用或访问模板。

使用ng-init来设置baseUrl(从服务器端的填充值)

 <html ng-app="app" ng-controller="AppController"> <head> <base href="{{baseUrl}}" ng-init="baseUrl = '@Model.BaseUrl'" /> </head> 

angular度控制器

  $scope.manageCustomerGroups = function () { openDialog($scope.baseUrl + 'content/templates/customerGroups.html'); } 

我有一个类似的问题,我用我的MVC页面中的一行代码解决它

 <base href="~/" /> 

一个简单的方法,我使用ASP.NET Razor(Web MVC),所以我得到的应用程序path,并将其作为应用程序的基础。

 <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Title</title> <meta name="description" content=""> @{ var appPath = Request.ApplicationPath.ToString(); if (!appPath.EndsWith("/")) { appPath = appPath + "/"; } } <base href="@appPath" /> 

在ng-init函数中传递一个参数,该参数包含虚拟目录的值(ASP.NET存储在Request.ApplicationPath中)。

 <div ng-controller="ControllerName" ng-init="init('@Request.ApplicationPath')"> 

在angular度控制器里面,在每个http调用中使用这个值作为URL的前缀。 您可以使用此function来组合path

 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; }