66

我有以下代码,在部署到测试服务器之前运行良好:

$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的正确方法。

4

9 回答 9

105

我建议在头部使用 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/";
    ...

不过只是我的看法。为您的应用程序做最简单的事情。

于 2013-06-09T19:39:20.360 回答
29

我建议定义一个包含全局配置的模块,然后您可以将其传递给您的应用程序:

// 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';
    ...
  }]);

每当基本路径更改时(例如,当您更改为另一台服务器或主机时),您只需在全局配置中更改它即可。

于 2013-06-14T15:28:21.293 回答
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()

于 2013-09-26T21:48:00.997 回答
4

使用 $location 服务 - 它会返回您的路径、哈希值、服务器地址……您需要的一切!您的电话将是 to$location.path()+"/GetUserList"或类似的东西。

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

于 2013-06-09T16:24:55.797 回答
3

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

<base href="~/" />
于 2016-08-19T13:48:39.747 回答
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');
    }
于 2015-02-17T15:09:47.723 回答
0

我只会使所有 URL 相对。

url: "../GetUserList",

反而

url: "GetUserList",

硬编码对<base href="/application_root/" /> 我来说听起来不是一个好主意,因为您可能需要将此环境更改为环境,并且依赖于虚拟目录名称。

于 2017-11-28T19:37:42.393 回答
0

一种简单的方法,我使用的是 ASP.NET Razor (Web MVC),所以我获取了应用程序路径并将其作为应用程序的基础。

<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" />
于 2017-09-28T07:20:16.553 回答
-1

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

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

在 Angular 控制器中,在每个 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;
}
于 2015-09-18T14:52:36.700 回答