2012-04-30 13 views
46

È possibile eseguire quanto segue da un file javascript in un'applicazione MVC?È possibile accedere all'oggetto MVC ViewBag dal file Javascript?

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

Attualmente genera l'errore:

reference to undefined XML name @ViewBag

+0

Ho fatto una domanda simile prima, spero che ti aiuti. http://stackoverflow.com/questions/10036903/is-it-better-to-use-embedded-javascript-or-a-separate-js-file-in-an-mvc3-view –

+1

The tl; dr of it è: utilizzare gli attributi dei dati per impostare i valori nella vista, quindi utilizzare jQuery per accedere a tali attributi di dati sul file .JS separato. –

risposta

74

Non credo ci sia attualmente un modo per fare questo. Il motore Razor non analizza i file Javascript, solo le visualizzazioni del rasoio. Tuttavia, si può realizzare quello che vuoi impostando le variabili all'interno della vostra vista 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> 

Come Joe fa notare nei commenti, il valore della stringa di cui sopra si romperà se c'è una sola offerta in esso. Se vuoi renderlo completamente rivestito di ferro, dovrai sostituire tutte le virgolette singole con virgolette singole sfuggite. Il problema è che tutte le barre improvvise diventano un problema. Ad esempio, se la tua stringa è "foo \' bar" e sostituisci la virgoletta singola, ciò che verrà fuori è "foo \\' bar" e avrai ripreso lo stesso problema. (. Questa è l'età antica difficoltà di codifica concatenati) Il modo migliore per gestire questa situazione è quello di trattare backslash e cita come speciali e assicurarsi che siano tutti sfuggito:

@{ 
     var safeStringValue = ViewBag.someStringValue 
      .Replace("\\", "\\\\") 
      .Replace("'", "\\'"); 
    } 
    var someStringValue = '@(safeStringValue)'; 
+2

Se si dispone di una singola quota nel ViewBag.someStringValue, questo non spezzerà il js? Credo che il modo corretto per farlo sia quello di usare un campo modulo nascosto (come si vede sotto questa risposta) –

+0

È un buon punto, Joe, e tu hai ragione: una sola citazione lo farebbe davvero male. Mi sento come se il metodo del campo modulo nascosto fosse terribilmente goffo, ma questo è più diretto. E il singolo problema di quotazione è gestito abbastanza facilmente ... aggiornerò la mia risposta di conseguenza, grazie per il suggerimento. –

+1

Fantastico, grazie! –

21
Non

in un file JavaScript, no.
Il file JavaScript potrebbe contenere una classe e è possibile creare un'istanza di una nuova istanza di tale classe nella vista, quindi è possibile passare i valori ViewBag nel costruttore della classe.

Oppure, se non è una classe, l'unica altra alternativa è utilizzare gli attributi data negli elementi HTML, assegnarli alle proprietà nella vista e recuperarli nel file JS.

si Supponendo che ha avuto questo ingresso:

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

Poi nel file JS si potrebbe ottenere utilizzando:

var myVal = $("#myInput").data("myValue"); 
+1

+1: questo è l'approccio più ampiamente accettato e quello che uso io stesso –

+1

Fare attenzione a memorizzare i dati del viewbag in elementi html, a seconda del tipo di dati e del tipo di applicazione che si sta creando, questo potrebbe essere un grave difetto di sicurezza. In alcuni casi può valere la pena di ristrutturare spostando alcune logiche da javascript al controller. (solo alcuni casi, come il mio caso adesso!) :) Buona risposta però! – Chris

4

Per fare questo il tuo Il file JavaScript dovrebbe essere pre-elaborato sul lato server. Essenzialmente, sarebbe diventare una visualizzazione ASP.NET di qualche tipo e i tag script che fanno riferimento al file farebbero essenzialmente riferimento a un'azione del controller che risponde con tale visualizzazione.

Sembra una lattina di worm che non vuoi aprire.

Poiché JavaScript è lato client, perché non impostare semplicemente il valore su un elemento lato client e interagire con JavaScript. È forse un ulteriore passo verso l'indirezione, ma sembra molto meno un mal di testa che creare una vista JavaScript.

Qualcosa di simile a questo:

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

Poi il file JavaScript esterno può fare riferimento alla variabile someValue JavaScript nell'ambito di applicazione di tale documento.

O anche:

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

Quindi è possibile accedere a tale input nascosto.

A meno che non venga in mente un modo davvero efficace per rendere il file JavaScript utilizzabile come vista. È certamente fattibile, e non riesco a trovare prontamente pensare a qualsiasi problema avessi (diverso dal brutto codice di visualizzazione dato che il motore di visualizzazione otterrà molto confuso su cosa sia JavaScript e cos'è Razor ... quindi aspettati un ton di <text> markup), quindi se si trova un modo perfetto per farlo sarebbe bello, anche se forse non intuitivo per qualcuno che ha bisogno di supportare il codice in seguito.

3

in Html:

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

in Script:

var customVal = $("#customInput").data("value"); 
+0

Questo deve essere selezionato come risposta !. Votato + –

-1

Creare una vista e restituire come una vista parziale:

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(); 
    } 
} 

Poi negli GlobalJS visualizzare aggiungere il codice javascript come (aggiungendo il // farà in studio intellisense visual leggerlo come JavaScript)

//<script> 

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

//</script> 

Poi, nel tuo parere definitivo è possibile aggiungere un riferimento al javascript proprio come questo.

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

Quindi nel controller di visualizzazione finale è possibile creare/passare il ViewBags e verrà visualizzato nel javascript.

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

Spero che sia d'aiuto.

-1

ho notato che rivelatore di errore built-in di Visual Studio tipo di ottiene goofy se si tenta di fare questo:

var intvar = @(ViewBag.someNumericValue); 

Perché @ (ViewBag.someNumericValue) ha il potenziale per valutare a nulla, che porterebbe ad essere generato il seguente erronea JavaScript:

var intvar = ; 

Se si è certi che someNemericValue sarà impostato su un tipo di dati numerici validi, si può evitare di avere Visual Studio avvisi effettuando le seguenti operazioni:

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

Questo potrebbe generare il seguente esempio:

var intvar = Number(25.4); 

e funziona per i numeri negativi. Nel caso in cui l'articolo non sia nel tuo viewbag, Number() viene valutato a 0.

Nessun avviso di Visual Studio! Ma assicurati che il valore sia impostato e sia numerico, altrimenti stai aprendo le porte a possibili attacchi di JavaScript injection o errori di run time.

-1

Nei controllori azione aggiuntivo:

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

per riprodurre il set di eccezioni b = 0, in modo che venga visualizzato il popup – Savita

0

Usa questo codice nel file .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> 
Problemi correlati