在AngularJS中使用服务调用的相对路径

时间:2013-06-09 16:19:50

标签: javascript angularjs

我有以下代码,在我部署到测试服务器之前工作正常:

$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。

9 个答案:

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