it-swarm.com.de

Verwenden eines relativen Pfads für einen Serviceabruf in AngularJS

Ich habe den folgenden Code, der einwandfrei funktioniert hat, bis ich ihn auf einem Testserver bereitgestellt habe:

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

Das Problem ist, dass ich in einem virtuellen Verzeichnis bereitgestellt habe und der folgende Aufruf versucht, GetUserList vom Server-Stamm aus zu erreichen. Dies ist sinnvoll, und ich kenne eine Reihe von Möglichkeiten, um das Problem zu beheben.

Was ich wissen möchte, ist die rechts Möglichkeit, die Service-URL auf eine Weise zu referenzieren, die portabel und in Angular wartbar ist.

66
Phil Sandler

Ich würde vorschlagen, ein HTML-Basistag im Kopf zu verwenden und alle diesbezüglichen Pfade zu codieren. In ASP.NET können Sie beispielsweise einen Verweis auf die Basis der Anwendung abrufen, bei der es sich möglicherweise um den Stammpfad der Site handelt, sodass die Verwendung eines Basis-Tags hilfreich ist. Bonus: Es funktioniert auch für jedes andere Gut.

Sie können einen Basispfad wie diesen haben:

<base href="/application_root/" />

... und dann sind Links wie "foo/bar.html" eigentlich "/application_root/foo/bar.html".

Ein weiterer Ansatz, den ich gerne verwende, besteht darin, benannte Links in den Header einzufügen. Ich habe oft einen API-Root an einem Ort und einen Direktiven-Template-Root an einem anderen Ort. Im Kopf füge ich dann einige Tags wie dieses hinzu:

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

... und benutze dann $ supply im Modul, um den Link href zu erhalten und ihn Services und Direktiven wie folgt zuzuweisen:

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

... und dann einem Dienst wie diesem hinzufügen:

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

Nur meine Meinung. Machen Sie die am wenigsten komplexe Sache für Ihre Anwendung.

104

Ich würde vorschlagen, ein Modul zu definieren, das eine globale Konfiguration enthält, die Sie dann um Ihre Anwendung herumgeben können:

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

Dann können Sie dank AngularJS Dependency Injection von überall in Ihrer Anwendung darauf zugreifen:

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

Wann immer sich der Basispfad ändert (z. B. wenn Sie zu einem anderen Server oder Host wechseln), müssen Sie ihn nur in Ihrer globalen Konfiguration ändern und fertig.

28
jvandemo

Ich konnte das <base> - Tag nicht verwenden, da meine Anwendung in einem Popup dynamisch aus einem anderen Ursprung erstellt wurde. Ich habe die andere Option in diesem Thread in Betracht gezogen, um so etwas wie eine basePath-Variable zu verwenden und sie in jedem $http, ng-src, templateUrl Etc. Zu verwenden

Aber das war ein bisschen umständlich, baute einen Abfangjäger, der jede URL ändert, bevor ein xhr erstellt wird

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

Und HTML auch

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

Ich empfehle jedoch, stattdessen das Tag <base> Zu verwenden, es sei denn, Sie verwenden window.popup ().

13
Endless

Verwenden Sie den $ location-Dienst - er gibt Ihren Pfad, den Hash, die Serveradresse zurück. Alles, was Sie brauchen! Ihr Anruf wäre $location.path()+"/GetUserList" oder etwas Ähnliches.

Siehe hier: http://docs.angularjs.org/guide/dev_guide.services.$location

4
Tiago Roldão

Ich hatte ein ähnliches Problem. Ich löse es mit nur einer Codezeile auf meiner MVC-Seite

<base href="~/" />
3
José Gomes

Die akzeptierte Antwort hat mir geholfen. Ich verwende Angular, das meine MVC-App bereitgestellt hat. Ich habe einen zusätzlichen Schritt ausgeführt, damit meine baseUrl in meinen angular Controllern für Web-API-Aufrufe verwendet werden kann oder für den Zugriff auf Vorlagen.

Verwenden von ng-init zum Festlegen der baseUrl (von einem serverseitig ausgefüllten Wert)

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

Winkelregler

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

Ich würde einfach alle URLs relativ machen.

url: "../GetUserList",

stattdessen

url: "GetUserList",

Hardcodierung für die, <base href="/application_root/" /> klingt für mich nicht nach einer guten Idee, da Sie diese Umgebung möglicherweise in eine andere Umgebung umwandeln müssen und die Abhängigkeit vom Namen des virtuellen Verzeichnisses besteht.

0
SubodhW

Auf einfache Weise verwende ich ASP.NET Razor (Web MVC), um den Anwendungspfad abzurufen und als Basis für die App zu verwenden.

<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" />
0
Mi.HTR