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