web-dev-qa-db-fra.com

Possible d'accéder à l'objet MVC ViewBag à partir d'un fichier Javascript?

Est-il possible de faire ce qui suit à partir d'un fichier javascript dans une application MVC?

$(function(){
   alert(@ViewBag.someValue);
}

Actuellement, l'erreur est générée:

référence à un nom XML non défini @ViewBag

58
Abe Miessler

Je ne crois pas qu'il y ait actuellement aucun moyen de le faire. Le moteur Razor n'analyse pas les fichiers Javascript, mais uniquement les vues Razor. Cependant, vous pouvez accomplir ce que vous voulez en définissant les variables dans votre vue Razor:

<script>
  var someStringValue = '@(ViewBag.someStringValue)';
  var someNumericValue = @(ViewBag.someNumericValue);
</script>
<!-- "someStringValue" and "someNumericValue" will be available in script -->
<script src="js/myscript.js"></script>

Comme Joe le souligne dans les commentaires, la valeur de chaîne ci-dessus sera rompue si elle contient un seul guillemet. Si vous voulez que cela soit complètement impeccable, vous devrez remplacer tous les guillemets simples par des guillemets simples échappés. Le problème est que toutes les barres soudaines deviennent un problème. Par exemple, si votre chaîne est "foo \' bar ", et vous remplacez la citation simple, ce qui sortira est" foo \\' bar ", et vous êtes de retour au même problème. (C’est la vieille difficulté de l’encodage en chaîne.) La meilleure façon de gérer cela est de traiter les barres obliques inverses et les guillemets comme spéciaux et de s’assurer qu’ils sont tous échappé:

  @{
      var safeStringValue = ViewBag.someStringValue
          .Replace("\\", "\\\\")
          .Replace("'", "\\'");
  }
  var someStringValue = '@(safeStringValue)';
89
Ethan Brown

Pas dans un fichier JavaScript, non.
Votre fichier JavaScript peut contenir une classe et vous pouvez instancier une nouvelle instance de cette classe dans la vue. Vous pouvez ensuite passer ViewBag valeurs dans le constructeur de la classe.

Si ce n’est pas une classe, votre seule autre alternative consiste à utiliser les attributs data dans vos éléments HTML, à les affecter aux propriétés de votre vue et à les récupérer dans le fichier JS.

En supposant que vous ayez eu cette entrée:

<input type="text" id="myInput" data-myValue="@ViewBag.MyValue" />

Ensuite, dans votre fichier JS, vous pouvez l’obtenir en utilisant:

var myVal = $("#myInput").data("myValue");
28
mattytommo

en HTML:

<input type="hidden" id="customInput" data-value = "@ViewBag.CustomValue" />

dans Script:

var customVal = $("#customInput").data("value");
13
aslanpayi

Pour ce faire, votre fichier JavaScript doit être prétraité côté serveur. Essentiellement, il devrait devenir une vue ASP.NET de quelque type que ce soit et les balises script qui référencent le fichier font essentiellement référence à une action du contrôleur qui répond à cette vue.

Cela ressemble à une boîte de Pandore que vous ne voulez pas ouvrir.

Puisque JavaScript est côté client, pourquoi ne pas simplement définir la valeur sur un élément côté client et laisser le JavaScript interagir avec cela. C'est peut-être une étape supplémentaire d'indirection, mais cela ressemble beaucoup moins à une migraine qu'à la création d'une vue JavaScript.

Quelque chose comme ça:

<script type="text/javascript">
    var someValue = @ViewBag.someValue
</script>

Ensuite, le fichier JavaScript externe peut référencer la variable JavaScript someValue dans la portée de ce document.

Ou même:

<input type="hidden" id="someValue" value="@ViewBag.someValue" />

Ensuite, vous pouvez accéder à cette entrée cachée.

À moins que vous ne trouviez un moyen vraiment astucieux de rendre votre fichier JavaScript utilisable en tant que vue. C'est certainement faisable, et je ne peux pas facilement penser à tous les problèmes que vous auriez (autres que le code de vue vraiment moche, car le moteur de vue deviendra très confus quant à ce qui est JavaScript et qu'est-ce que Razor ... attendez-vous donc à un ton de <text> _ markup), donc si vous trouvez un moyen astucieux de le faire, ce serait plutôt cool, bien que cela ne soit peut-être pas intuitif pour quelqu'un qui a besoin de supporter le code plus tard.

5
David

J'ai remarqué que le détecteur d'erreurs intégré de Visual Studio devient maladroit si vous essayez ceci:

var intvar = @(ViewBag.someNumericValue);

Parce que @ (ViewBag.someNumericValue) a le potentiel de ne rien évaluer, ce qui entraînerait la génération du code JavaScript erroné suivant:

var intvar = ;

Si vous êtes certain que someNemericValue sera défini sur un type de données numérique valide, vous pouvez éviter les avertissements Visual Studio en procédant comme suit:

var intvar = Number(@(ViewBag.someNumericValue));

Cela pourrait générer l'exemple suivant:

var intvar = Number(25.4);

Et cela fonctionne pour les nombres négatifs. Si l'élément n'est pas dans votre panier, Number () est évalué à 0.

Finis les avertissements Visual Studio! Mais assurez-vous que la valeur est définie et numérique, sinon vous ouvrez la porte à d'éventuelles attaques par injection JavaScript ou à des erreurs d'exécution.

1
JSideris

Créez une vue et renvoyez-la sous forme de vue partielle:

public class AssetsController : Controller
{
    protected void SetMIME(string mimeType)
    {
        this.Response.AddHeader("Content-Type", mimeType);
        this.Response.ContentType = mimeType;
    }

    // this will render a view as a Javascript file
    public ActionResult GlobalJS()
    {
        this.SetMIME("text/javascript");
        return PartialView();
    }
}

Ensuite, dans la vue GlobalJS, ajoutez le code javascript de la manière suivante (en ajoutant le //, Visual Studio intellisense le lira en tant que script Java).

//<script>

    $(document).ready(function () {
       alert('@ViewBag.PropertyName');
    }); 

//</script>

Ensuite, dans votre vue finale, vous pouvez ajouter une référence au javascript comme ceci.

<script src="@Url.Action("GlobalJS", "Assets")"></script> 

Ensuite, dans votre contrôleur de vue final, vous pouvez créer/passer vos ViewBags et ils seront rendus dans votre javascript.

public class MyFinalViewController : Controller
{
    public ActionResult Index()
    {
        ViewBag.PropertyName = "My ViewBag value!";
        return View();
    }
}

J'espère que ça aide.

1
OAK

Utilisez ce code dans votre fichier .cshtml.

 @{
    var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
    var val = jss.Serialize(ViewBag.somevalue); 
    }

    <script>
        $(function () {
            var val = '@Html.Raw(val)';
            var obj = $.parseJSON(val);
            console.log(0bj);
    });
    </script>
1
bax 1188

Dans l'action des contrôleurs, ajoutez:

 public ActionResult Index()
        {
            try
            {
                int a, b, c;
                a = 2; b = 2;
                c = a / b;
                ViewBag.ShowMessage = false;
            }
            catch (Exception e)
            {
                ViewBag.ShowMessage = true;
                ViewBag.data = e.Message.ToString();
            }
            return View();    // return View();

        }

in Index.cshtml
Place at the bottom:

<input type="hidden" value="@ViewBag.data" id="hdnFlag" />

@if (ViewBag.ShowMessage)
{
    <script type="text/javascript">

        var h1 = document.getElementById('hdnFlag');

        alert(h1.value);

    </script>
    <div class="message-box">Some Message here</div>
}
0
Savita