Accéder à la propriété de modèle de MVC à partir de Javascript

148

J'ai le modèle suivant qui est enveloppé dans mon modèle de vue

public class FloorPlanSettingsModel
{
    public int Id { get; set; }
    public int? MainFloorPlanId { get; set; }
    public string ImageDirectory { get; set; }
    public string ThumbnailDirectory { get; set; }
    public string IconsDirectory { get; set; }
}

Comment accéder à l'une des propriétés ci-dessus à partir de Javascript?

J'ai essayé ceci, mais je suis devenu "indéfini"

var floorplanSettings = "@Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);
Référence nulle
la source
5
Pour être clair, ce qui se passe, c'est que vous définissez la valeur de la variable JavaScript sur la valeur de la variable C # "Model.FloorPlanSettings", qui sera la valeur .ToString () de cette classe (une chaîne). Ensuite, vous essayez d'alerter une propriété JavaScript appelée "IconsDirectory" sur la variable de chaîne JavaScript que vous venez de créer. Vous obtenez indéfini car une chaîne JavaScript n'a pas de propriété "IconsDirectory".
Joel Cochran
Fourni un scénario de test complet et expliqué tous les scénarios d'attribution de données de modèle à une variable javascript,
Rajshekar Reddy
Cela ne fonctionne pas en dehors de la vue (cshtml). c'est-à-dire dans un fichier .js externe référencé par la vue.
Spencer Sullivan

Réponses:

240

Vous pouvez prendre tout votre modèle côté serveur et le transformer en un objet Javascript en procédant comme suit:

var model = @Html.Raw(Json.Encode(Model));

Dans votre cas, si vous voulez juste l'objet FloorPlanSettings, passez simplement la Encodeméthode that property:

var floorplanSettings = @Html.Raw(Json.Encode(Model.FloorPlanSettings));
Justin Helgerson
la source
1
Juste pour confirmer, il n'est pas nécessaire d'ajouter un; à la fin? Parce que je reçois une invite de VS indiquant que l'instruction n'est pas terminée. Mais quand j'essaye d'ajouter; le code ne s'exécute pas
Null Reference
1
Que savez-vous, j'ai aussi la même erreur dans mes différents projets. N'y faites pas attention; c'est Visual Studio qui essaie d'aider, mais c'est faux dans ce cas. Le code HTML et le script qui sont envoyés au navigateur sont corrects.
Justin Helgerson
1
Pour moi, cela a fonctionné: var myModel = @ {@ Html.Raw (Json.Encode (Model));}
masqué le
1
Ne fonctionne pas si le modèle est la valeur initiale (Créer une page au lieu de Modifier la page) et "ReferenceError: Model is not defined" est rencontré.
Jack
2
Dans ASP.Net Core, Json.Serialize ()
Mohammed Noureldin
131

Contenu de la réponse

1) Comment accéder aux données du modèle dans le bloc de code Javascript / Jquery dans le .cshtmlfichier

2) Comment accéder aux données du modèle dans le bloc de code Javascript / Jquery dans le .jsfichier

Comment accéder aux données du modèle dans le bloc de code Javascript / Jquery dans le .cshtmlfichier

Il existe deux types d' Modelaffectations de variable c # ( ) à une variable JavaScript.

  1. Cession de propriété - types de données de base comme int, string, DateTime(ex: Model.Name)
  2. Affectation d'objets - personnalisés ou des cours encastrables (ex: Model, Model.UserSettingsObj)

Regardons dans les détails de ces deux affectations.

Pour le reste de la réponse, considérons le AppUsermodèle ci-dessous comme un exemple.

public class AppUser
{
    public string Name { get; set; }
    public bool IsAuthenticated { get; set; }
    public DateTime LoginDateTime { get; set; }
    public int Age { get; set; }
    public string UserIconHTML { get; set; }
}

Et les valeurs que nous attribuons à ce modèle sont

AppUser appUser = new AppUser
{
    Name = "Raj",
    IsAuthenticated = true,
    LoginDateTime = DateTime.Now,
    Age = 26,
    UserIconHTML = "<i class='fa fa-users'></i>"
};

Attribution de propriété

Permet d'utiliser une syntaxe différente pour l'affectation et d'observer les résultats.

1) Sans placer l'attribution de propriété entre guillemets

var Name = @Model.Name;  
var Age = @Model.Age;
var LoginTime = @Model.LoginDateTime; 
var IsAuthenticated = @Model.IsAuthenticated;   
var IconHtml = @Model.UserIconHTML;  

entrez la description de l'image ici

Comme vous pouvez le voir, il y a quelques erreurs, Rajet Trueest considéré comme des variables javascript et comme elles n'existent pas, c'est une variable undefinederreur. Là où, comme pour la variable dateTime, l'erreur est que les unexpected numbernombres ne peuvent pas avoir de caractères spéciaux, les balises HTML sont converties en ses noms d'entité afin que le navigateur ne mélange pas vos valeurs et le balisage HTML.

2) Affectation de propriété enveloppante dans les devis.

var Name = '@Model.Name';
var Age = '@Model.Age';
var LoginTime = '@Model.LoginDateTime';
var IsAuthenticated = '@Model.IsAuthenticated';
var IconHtml = '@Model.UserIconHTML'; 

entrez la description de l'image ici

Les résultats sont valides, donc mettre l'attribution de propriété entre guillemets nous donne une syntaxe valide. Mais notez que le nombre Ageest maintenant une chaîne, donc si vous ne voulez pas que nous puissions simplement supprimer les guillemets et il sera rendu comme un type de nombre.

3) En utilisant @Html.Rawmais sans le mettre entre guillemets

 var Name = @Html.Raw(Model.Name);
 var Age = @Html.Raw(Model.Age);
 var LoginTime = @Html.Raw(Model.LoginDateTime);
 var IsAuthenticated = @Html.Raw(Model.IsAuthenticated);
 var IconHtml = @Html.Raw(Model.UserIconHTML);

entrez la description de l'image ici

Les résultats sont similaires à ceux de notre cas de test 1. Cependant, l'utilisation @Html.Raw()de la HTMLchaîne nous a montré des changements. Le HTML est conservé sans changer ses noms d'entité.

À partir de la documentation Html.Raw ()

Enveloppe le balisage HTML dans une instance HtmlString afin qu'il soit interprété comme un balisage HTML.

Mais nous avons toujours des erreurs dans d'autres lignes.

4) Utiliser @Html.Rawet également l'envelopper entre guillemets

var Name ='@Html.Raw(Model.Name)';
var Age = '@Html.Raw(Model.Age)';
var LoginTime = '@Html.Raw(Model.LoginDateTime)';
var IsAuthenticated = '@Html.Raw(Model.IsAuthenticated)';
var IconHtml = '@Html.Raw(Model.UserIconHTML)';

entrez la description de l'image ici

Les résultats sont bons avec tous les types. Mais nos HTMLdonnées sont maintenant cassées et cela cassera les scripts. Le problème est que nous utilisons des guillemets simples 'pour envelopper les données et même les données ont des guillemets simples.

Nous pouvons surmonter ce problème avec 2 approches.

1) utilisez des guillemets doubles " "pour envelopper la partie HTML. Comme les données internes n'ont que des guillemets simples. (Assurez-vous qu'après l'encapsulation avec des guillemets doubles, il n'y en a pas non plus "dans les données)

  var IconHtml = "@Html.Raw(Model.UserIconHTML)";

2) Échappez à la signification du caractère dans votre code côté serveur. Comme

  UserIconHTML = "<i class=\"fa fa-users\"></i>"

Conclusion de la cession de propriété

  • Utilisez des guillemets pour les types de données non numériques.
  • N'utilisez pas de guillemets pour les types de données numériques.
  • Utilisez Html.Rawpour interpréter vos données HTML telles quelles.
  • Prenez soin de vos données HTML pour soit échapper à la signification des guillemets côté serveur, soit utiliser une citation différente de celle des données lors de l'affectation à la variable javascript.

Affectation d'objets

Permet d'utiliser une syntaxe différente pour l'affectation et d'observer les résultats.

1) Sans placer l'attribution d'objets entre guillemets.

  var userObj = @Model; 

entrez la description de l'image ici

Lorsque vous affectez un objet ac # à une variable javascript, la valeur .ToString()de cet objet sera attribuée. D'où le résultat ci-dessus.

2 Mise en place de l'attribution d'objets entre guillemets

var userObj = '@Model'; 

entrez la description de l'image ici

3) Utilisation Html.Rawsans guillemets.

   var userObj = @Html.Raw(Model); 

entrez la description de l'image ici

4) Utilisation Html.Rawavec des guillemets

   var userObj = '@Html.Raw(Model)'; 

entrez la description de l'image ici

Cela Html.Rawne nous a guère servi lors de l'affectation d'un objet à une variable.

5) Utilisation Json.Encode()sans guillemets

var userObj = @Json.Encode(Model); 

//result is like
var userObj = {&quot;Name&quot;:&quot;Raj&quot;,
               &quot;IsAuthenticated&quot;:true,
               &quot;LoginDateTime&quot;:&quot;\/Date(1482572875150)\/&quot;,
               &quot;Age&quot;:26,
               &quot;UserIconHTML&quot;:&quot;\u003ci class=\&quot;fa fa-users\&quot;\u003e\u003c/i\u003e&quot;
              };

Nous voyons des changements, nous voyons que notre modèle est interprété comme un objet. Mais nous avons changé ces caractères spéciaux en entity names. Mettre également la syntaxe ci-dessus entre guillemets n'est pas d'une grande utilité. Nous obtenons simplement le même résultat entre guillemets.

À partir de la documentation de Json.Encode ()

Convertit un objet de données en une chaîne au format JavaScript Object Notation (JSON).

Comme vous avez déjà rencontré ce entity Nameproblème avec l'attribution de propriété et si vous vous en souvenez, nous l'avons surmonté avec l'utilisation de Html.Raw. Alors essayons ça. Permet de combiner Html.RawetJson.Encode

6) En utilisant Html.Rawet Json.Encodesans guillemets.

var userObj = @Html.Raw(Json.Encode(Model));

Le résultat est un objet Javascript valide

 var userObj = {"Name":"Raj",
     "IsAuthenticated":true,
     "LoginDateTime":"\/Date(1482573224421)\/",
     "Age":26,
     "UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
 };

entrez la description de l'image ici

7) Utilisation Html.Rawet Json.Encodeentre guillemets.

var userObj = '@Html.Raw(Json.Encode(Model))';

entrez la description de l'image ici

Comme vous le voyez, l'emballage avec des guillemets nous donne des données JSON

Conslusion sur l'attribution d'objets

  • Utilisez Html.Rawet Json.Encodeen combinaison pour affecter votre objet à une variable javascript en tant qu'objet JavaScript .
  • Utilisez Html.Rawet Json.Encodeenveloppez-le également quotespour obtenir un JSON

Remarque: si vous avez observé que le format de données DataTime n'est pas correct. En effet, comme indiqué précédemment, Converts a data object to a string that is in the JavaScript Object Notation (JSON) formatet JSON ne contient pas de datetype. D' autres options pour résoudre ce problème est d'ajouter une autre ligne de code pour gérer ce type seul , en date javascipt () objet

var userObj.LoginDateTime = new Date('@Html.Raw(Model.LoginDateTime)'); 
//without Json.Encode


Comment accéder aux données du modèle dans le bloc de code Javascript / Jquery dans le .jsfichier

La syntaxe de Razor n'a aucune signification dans le .jsfichier et nous ne pouvons donc pas utiliser directement notre modèle dans un .jsfichier. Cependant, il existe une solution de contournement.

1) La solution utilise des variables globales javascript .

Nous devons attribuer la valeur à une variable javascipt à portée globale, puis utiliser cette variable dans tous les blocs de code de vos fichiers .cshtmlet .js. La syntaxe serait donc

<script type="text/javascript">
  var userObj = @Html.Raw(Json.Encode(Model)); //For javascript object
  var userJsonObj = '@Html.Raw(Json.Encode(Model))'; //For json data
</script>

Avec cela en place, nous pouvons utiliser les variables userObjet au userJsonObjfur et à mesure des besoins.

Remarque: Personnellement, je ne suggère pas d'utiliser des variables globales car cela devient très difficile pour la maintenance. Cependant, si vous n'avez pas d'autre option, vous pouvez l'utiliser avec une convention de dénomination appropriée .. quelque chose comme userAppDetails_global.

2) En utilisant la fonction () ou closure Envelopper tout le code qui dépend des données du modèle dans une fonction. Et puis exécutez cette fonction à partir du .cshtmlfichier.

external.js

 function userDataDependent(userObj){
  //.... related code
 }

.cshtml fichier

 <script type="text/javascript">
  userDataDependent(@Html.Raw(Json.Encode(Model))); //execute the function     
</script>

Remarque: votre fichier externe doit être référencé avant le script ci-dessus. Sinon, la userDataDependentfonction n'est pas définie.

Notez également que la fonction doit également avoir une portée globale. Donc, quelle que soit la solution, nous devons traiter avec des acteurs mondiaux.

Rajshekar Reddy
la source
La propriété Model peut-elle être mise à jour en javascript et envoyée à la méthode d'action du contrôleur?
@sortednoun oui vous pouvez, Vous pouvez renvoyer les données modifiées à partir d'un formulaire, Ou si vous ne voulez pas recharger la page, vous pouvez utiliser AJAX
Rajshekar Reddy
Je n'utilisais pas ajax, et j'ai juste essayé de modifier la propriété du modèle en javascript. mais lors de la soumission du formulaire, ce changement n'a pas été reflété dans le modèle. Je faisais quelque chose comme: var model = @ Html.Raw (Json.Encode (Model)); model.EventCommand = "valeur mise à jour"; Cela m'a donné le modèle correctement et la valeur mise à jour, mais lors de la soumission, le changement manquait dans la méthode d'action. (Bien que j'aie fait la même chose en utilisant le contrôle Html caché et que je l'ai lié à EventCommand et mis à jour sa valeur en javascript. Mais je me demande si je pourrais faire de même directement pour le modèle?)
@sortednoun J'ai compris votre point, var model = @Html.Raw(Json.Encode(Model));cela va créer un objet javascript model qui n'a aucun lien avec le modèle C # que vous passez à la vue. En fait, il n'y en aura pas Modelaprès le rendu de la vue. Ainsi, le formulaire dans l'interface utilisateur n'aura aucune idée des modifications des données d'objet javascript. Vous devez maintenant transmettre tout ce modèle modifié au contrôleur via AJAX, ou vous devez mettre à jour la valeur de vos contrôles d'entrée dans le formulaire en utilisant javascript.
Rajshekar Reddy
Although I did the same thing using hidden Html control and bound it to EventCommand and updated it's value in javascript. But wondering if could do same directly to model?pour cette déclaration .. il n'y a pas EventCommand de MVC, c'est pour les formulaires Web où il y a une connexion entre l'interface utilisateur et les actions du serveur, dans MVC, tout est séparé. Le seul moyen pour vous d'interagir avec le contrôleur est via AJAX, Soumettre un formulaire ou Demande de nouvelle page (recharger aussi)
Rajshekar Reddy
21

essayez ceci: (vous avez manqué les guillemets simples)

var floorplanSettings = '@Html.Raw(Json.Encode(Model.FloorPlanSettings))';
danmbuen
la source
1
@JuanPieterse avec des citations vous donne un JSONsans guillemets vous donne un javascript Object. Vérifiez ma réponse dans le même fil pour plus de détails. stackoverflow.com/a/41312348/2592042
Rajshekar Reddy
Ce n'est pas vrai, la solution @danmbuen a fonctionné dans mon cas, j'ai eu des problèmes et l'envelopper entre des guillemets simples a fonctionné comme un charme, MERCI;)
Dimitri
4

Emballer la propriété du modèle autour des parens a fonctionné pour moi. Vous obtenez toujours le même problème avec Visual Studio se plaignant du point-virgule, mais cela fonctionne.

var closedStatusId = @(Model.ClosedStatusId);
FROgistique
la source
0

Si l' erreur «ReferenceError: Model is not defined» est déclenchée, vous pouvez essayer d'utiliser la méthode suivante:

$(document).ready(function () {

    @{  var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
         var json = serializer.Serialize(Model);
    }

    var model = @Html.Raw(json);
    if(model != null && @Html.Raw(json) != "undefined")
    {
        var id= model.Id;
        var mainFloorPlanId = model.MainFloorPlanId ;
        var imageDirectory = model.ImageDirectory ;
        var iconsDirectory = model.IconsDirectory ;
    }
});

J'espère que cela t'aides...

Murat Yıldız
la source
0

Je sais qu'il est trop tard mais cette solution fonctionne parfaitement pour le framework .net et le noyau .net:

@ System.Web.HttpUtility.JavaScriptStringEncode ()

Amer Jamaeen
la source