web-dev-qa-db-fra.com

Comment passer des données d'asp.NET MVC à Angular2

Quel est le meilleur moyen de transmettre des données d’un contrôleur ASP.NET MVC à un composant Angular 2.0? Par exemple, nous utilisons le modèle MVC ASP.NET et souhaitons en envoyer une version JSON à Angular afin que nous puissions l’utiliser dans Angular.

Au moment où le contrôleur sert la vue, nous sommes déjà en mesure de transmettre certaines données à Angular2 (le modèle). Donc, l'appel supplémentaire AJAX pour récupérer ces données n'est pas requis. 

Cependant, je lutte pour "l'injecter" dans la composante angulaire. Comment est-ce que tu fais ça? Des bonnes références pour cela? Comme vous l'avez peut-être remarqué, je suis assez novice dans Angular2.

Mon index.cshtml ressemble à ceci. 

<div class="container">
<div>
    <h1>Welcome to the Angular 2 components!</h1>
</div>
<div class="row">
    <MyAngular2Component>
        <div class="alert alert-info" role="alert">
            <h3>Loading...</h3>
        </div>
    </MyAngular2Component>
</div>
</div>

Sincères amitiés,

Rob

18
Rob Van Pamel

Le meilleur moyen que j’ai trouvé pour transmettre des données à partir de MVC (ou de toute page d’hébergement/de démarrage) consiste à spécifier les données en tant qu’attribut sur le composant démarré et à utiliser ElementRef pour extraire directement la valeur.

Vous trouverez ci-dessous un exemple pour MVC dérivé de this answer , dans lequel il est impossible d'utiliser @Input pour les composants de niveau racine.

Exemple:

//index.cshtml
<my-app username="@ViewBag.UserName">
    <i class="fa fa-circle-o-notch fa-spin"></i>Loading...
</my-app>


//app.component.ts
import {Component, Input, ElementRef} from '@angular/core';

@Component({
    selector: 'my-app',
    template: '<div> username: <span>{{username}}</span> </div>'
})
export class AppComponent {
    constructor(private elementRef: ElementRef) {}

    username: string = this.elementRef.nativeElement.getAttribute('username')
}

Si vous souhaitez récupérer des données plus complexes qui ne conviennent pas à un attribut, vous pouvez utiliser la même technique, il suffit de placer les données dans un élément HTML <input type='hidden'/> ou un élément masqué <code> et d'utiliser JS brut pour récupérer la valeur.

myJson: string = document.getElementById("myJson").value

Avertissement: Accéder au DOM directement à partir d'une application liée aux données telle que Angular, rompt le modèle de liaison de données et doit être utilisé avec prudence.

14
Joseph Gabriel

Vous voudrez peut-être rechercher des questions similaires relatives à AngularJS, et non à Angular 2, car l’essentiel de l’essentiel reste le même: 

  • vous voulez que votre moteur Razor côté serveur rende un type de vue (c'est-à-dire HTML ou JS directement) 
  • cette vue contient un modèle JS dans lequel une partie du contenu est renseignée à partir d'une instance de modèle de serveur ou de toute façon des données de serveur (par exemple, une ressource, un dictionnaire, etc.).
  • pour remplir correctement une variable JS à partir de Razor, les données côté serveur C # doivent être sérialisées correctement au format JSON.

Dans ce message de Marius Schulz, vous pouvez voir qu’il sérialise les données et les utilise pour remplir un modèle de composant AngularJS value:

<script>
  angular.module("hobbitModule").value("companionship", @Html.Raw(Model));
</script>

Quelque chose de similaire pourrait être fait pour injecter des données, par ex. dans window.myNamespace.myServerData, puis lancez Angular2 avec cette valeur parmi d’autres fournisseurs.

Dans this post de Roel van Lisdonk, une approche similaire est utilisée, encore une fois, pour remplir un modèle basé sur AngularJS, avec cette directive ng-init:

<div ng-controller="main"
     ng-init="resources={ textFromResource: '@WebApplication1.Properties.Resources.TextFromResource'}">
  <h1>{{ title }}</h1>
  {{ resources.textFromResource }}
</div>

Comme le souligne le premier message, il y a quelque chose à penser (coller ici):

Un mot d'avertissement: la méthode que je suis sur le point d'utiliser ne convient probablement pas à de grandes quantités de données. Comme les données JavaScript sont intégrées à la réponse HTML, elles sont envoyées par câble chaque fois que vous demandez cette page. 

De plus, si les données sont spécifiques à l'utilisateur authentifié, la réponse ne peut plus être mise en cache et transmise à différents utilisateurs. Veuillez garder cela à l'esprit lorsque vous envisagez d'amorcer vos applications angulaires avec des données .NET de cette façon.

La deuxième partie risque moins de poser problème si votre page servie est déjà dynamique côté serveur, c'est-à-dire si des bits ont déjà été renseignés dans les données côté serveur.

HTH

2
superjos

Vous pouvez utiliser la fonction Input exposée par @angular/core. J'ai par exemple un composant Angular 2 pour afficher des messages d'information à l'intention de l'utilisateur de l'application.

Mon modèle HTML prend une propriété angulaire 2 Message 

<div class="alert alert-info col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-10 col-xs-offset-1">
    <i class="fa fa-info-circle"></i> {{ Message }}
</div>

La propriété Message est transmise en tant qu'entrée à mon composant Angular 2 nommé informationmessage.component.ts, par exemple

import { Component, Input } from '@angular/core';

@Component({
    selector: 'informationmessage',
    templateUrl: '../Templates/informationmessage.component.html'
})
export class InformationMessageComponent {
    @Input() Message: string;
}

Je passe ensuite les données à ma InformationMessageComponent en utilisant la liaison de propriété dans la page HTML, par exemple. 

<informationmessage [Message]="InformationMessage"></informationmessage>

Vous pouvez remplacer InformationMessage dans l'exemple ci-dessus par les données que vous obtenez de votre contrôleur MVC, par exemple

<informationmessage [Message]="@Model.InformationMessage"></informationmessage>

Remarque: Je n'ai pas testé ce scénario, mais il n'y a aucune raison technique pour que cela ne fonctionne pas. En fin de journée, vous ne faites que lier une valeur à une propriété Angular 2.

2
user65439

src/ApplicationConfiguration.ts

export class ApplicationConfiguration {
    public setting1: string;
    public setting2: string;
}

src/main.ts

declare var config : ApplicationConfiguration;
var providers = [{ provide: ApplicationConfiguration, useValue: config }];
platformBrowserDynamic(providers).bootstrapModule(AppModule)
.catch(err => console.log(err));

src/index.html

  <script type="text/javascript">
    var config = {setting1: "value1", setting2: "value2"};
  </script>

src/app/app.component.ts

export class AppComponent {

  private _config : ApplicationConfiguration;

  constructor(config: ApplicationConfiguration) {

    this._config = config;

  }

}
1
user9742894

Vous devez d’abord regrouper vos services et vos contrôleurs dans des fichiers de module séparés et charger les services avant les contrôleurs . Par exemple:

dist
|--services.js
|--controllers.js

Ensuite, vous devez charger le code JavaScript des services via le résultat JavaScript ASP.NET MVC. Ici, vous devez injecter vos données de démarrage.

public class ScriptController: Controller
{
  public ActionResult GetServices(){
   string file= File.ReadAllText(Server.MapPath("~dist/services.js"));
   //modify the file to inject data or 
   var result = new JavaScriptResult();         
   result.Script = file;
   return result;     
}

Ensuite, dans le fichier index.html, chargez les scripts comme suit

<script src="/script/getservices"></script>
<script src="/dist/controller.js"></script>

De cette façon, vous pouvez injecter des données dans le code angulaire lors du chargement. Cependant, même cela a un impact sur les performances en raison du temps passé à extraire la vue, à la compilation de la vue et à la liaison des données à la vue. Pour un chargement initial, les performances peuvent encore être améliorées si vous utilisez le rendu côté serveur.

1
Jigar

J'ai trouvé une solution beaucoup plus simple. N'essayez pas d'obtenir l'attribut dans le constructeur! Utilisez plutôt ngOnInit()hook . La propriété sera accessible tant qu'elle aura été décorée avec @Input(). Il semble simplement qu'il ne soit pas disponible au moment où le constructeur est appelé.

Composant HTML:

<MyComponent [CustomAttribute]="hello"></MyComponent>

Composant TS:

export class MyComponentComponent {
    @Input()
    public CustomAttribute: string;

    constructor() {}

    ngOnInit() {
        console.log("Got it! " + this.CustomAttribute);
    }
}
0
Eraph