我有以下代码,在我部署到测试服务器之前工作正常:
$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。
答案 0 :(得分:104)
我建议在头部使用HTML基本标记,并编码与此相关的所有路径。例如,在ASP.NET中,您可以获得对应用程序基础的引用,该引用可能是也可能不是站点的根路径,因此使用基本标记会有所帮助。奖励:它也适用于所有其他资产。
您可以拥有这样的基本路径:
<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/";
...
只是我的意见。为您的应用程序做最简单的事情。
答案 1 :(得分:28)
我建议定义一个包含全局配置的模块,然后可以在应用程序中传递:
// Module specific configuration
angular.module('app.config')
.value('app.config', {
basePath: '/' // Set your base path here
});
然后,由于AngularJS依赖注入,您可以从应用程序中的任何位置访问它:
// 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';
...
}]);
每当基本路径发生变化时(例如,当您更改为其他服务器或主机时),您只需在全局配置中更改它即可。
答案 2 :(得分:13)
我无法使用<base>
标记,因为我的应用程序是在另一个原始动态弹出窗口中创建的。我正在考虑此线程中的其他选项使用类似basePath变量的东西并在每个$http, ng-src, templateUrl
等中使用它
但这有点开销,建立了一个拦截器,在xhr生成之前改变每个url
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>
但我确实建议使用<base>
标记,除非您使用的是window.popup()
答案 3 :(得分:4)
使用$ location服务 - 它将返回您的路径,哈希,服务器地址..您需要的一切!您的电话将是$location.path()+"/GetUserList"
或类似的内容。
见这里:http://docs.angularjs.org/guide/dev_guide.services.$location
答案 4 :(得分:3)
我有类似的问题 我用MVC页面中的一行代码来解决它
<base href="~/" />
答案 5 :(得分:2)
接受的答案对我有帮助。我正在使用Angular提供我的MVC应用程序。 我采取了一个额外的步骤,以便我的baseUrl可以在我的角度控制器中用于web api调用或访问模板。
使用ng-init设置baseUrl(从服务器端填充的值)
<html ng-app="app" ng-controller="AppController">
<head>
<base href="{{baseUrl}}" ng-init="baseUrl = '@Model.BaseUrl'" />
</head>
角度控制器
$scope.manageCustomerGroups = function () {
openDialog($scope.baseUrl + 'content/templates/customerGroups.html');
}
答案 6 :(得分:0)
一个简单的方法,我正在使用ASP.NET Razor(Web MVC),因此我获得了Application路径并将其作为app的基础。
<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" />
答案 7 :(得分:0)
我只会让所有网址相对。
url: "../GetUserList",
而不是
url: "GetUserList",
对<base href="/application_root/" />
进行硬编码对我来说不太好,因为您可能需要将此环境更改为环境,并且依赖于虚拟目录名称。
答案 8 :(得分:-1)
在ng-init函数中传递一个包含虚拟目录值的参数(int ASP.NET存储在Request.ApplicationPath中)。
<div ng-controller="ControllerName" ng-init="init('@Request.ApplicationPath')">
在角度控制器内,在每次http调用中使用此值作为URL的前缀。您可以使用此功能组合路径
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;
}