2011-12-19 10 views
17

Utilizzo il motore di visualizzazione Razor ASP.Net MVC 3.MVC 3 Vista rasoio: generazione di JavaScript da un valore di modello booleano

Ho un obbligo di generare codice JavaScript nella mia vista in base a un valore nel mio modello di vista. Il valore che devo usare è un valore booleano, per questo esempio lo chiamiamo IsSet.

Quindi quello che voglio fare è creare un booleano JavaScript basato su questo valore che posso usare nello script in seguito.

Tenete presente che per tutti al di sotto esempi che ho questo pezzo di codice nella parte superiore del mio punto di vista ...

@{ string IsSet = Model.IsSet ? "true" : "false"; } 

NOTA: Tutti gli esempi che seguono sono JavaScript.

Primo tentativo ...

var IsSet = @(IsSet); 

... questo in realtà funziona, il problema è si rompe l'auto-formattazione (CTRL + E, D) in VS 2010 a causa di mal formattato JavaScript - come ci si potrebbe aspettare, e questo non è accettabile.

Secondo tentativo ...

var IsSet = "@(IsSet)"; 

... Lo so, JavaScript è intelligente, che si auto-analizzare la mia stringa quando necessario. Ooops, ho dimenticato che si tratta di un tipo di stringa e qualsiasi cosa diversa da vuota valuta true.

terzo tentativo ...

var IsSet = Boolean("@(IsSet)"); 

.... sicuramente questo funzionerà ... no, convertire stringa non vuota su true nuovo (male parser!)

Quarto tentare ...

var IsSet = "@(IsSet)" === "true"; 

Finalmente qualcosa che funziona, ma non sembra grande per me.

Lo userò se necessario, ma alla fine la mia domanda è: esiste un modo migliore per gestire questo tipo di situazione? Forse, il comportamento indesiderato nel mio primo tentativo è solo qualcosa che Microsoft potrebbe aver trascurato?

Se qualcuno ha un bel quinto tentativo per me, sarebbe bello.

La cosa importante per me è che l'auto-formattazione in VS 2010 non rompe

Grazie

+0

Dovrei essere d'accordo con il tuo primo tentativo - che mi sembra il più naturale per me, dato che non stai stringendo e poi lanci qualcosa che era già un Boolean in primo luogo! Ho usato questa tecnica molto nel mio codice Razor/JS e sembra funzionare bene, e non ho riscontrato alcun problema con la formattazione automatica, ma uso ReSharper in modo forse che lo risolva automaticamente! –

+0

Uso ReSharper e continuo a riscontrare problemi di formattazione automatica, quindi non sono sicuro che sia il motivo per cui non si verificano problemi di formattazione. Il problema della formattazione automatica e della maiuscola si verifica quando le variabili del Razor con cassa Pascal vengono visualizzate in punti in cui il formattatore applica la denominazione minuscola, come i nomi dei tag HTML o il codice JS (prevalentemente CamelCase; in particolare, il formattatore viene attivato quando viene indentata automaticamente si verifica ... Quindi Chris, ho l'impressione che potresti aver avuto uno scenario diverso? –

risposta

7

Versione 1 è l'unico di quelli che voterei anche se lavorassero tutti, perché è il più leggibile.Sfortunatamente non ho VS in casa quindi non posso provarlo per vedere quale sia il problema di formattazione automatica, ma se possibile vorrei ignorare il problema e andare avanti e usare quella versione dato che c'è niente di veramente sbagliato con il codice - è solo VS che è confuso. (Sta dicendo VS sta cercando di interpretare il tutto come JS e quindi trovarlo non valida?)

Ma se volete alcune altre opzioni:

quinto tentativo ...

@{ string IsSet = Model.IsSet ? "true" : ""; } 

var isSet = !!"@(IsSet)"; 
// OR 
var isSet = Boolean("@(IsSet)"); 

Trasforma il valore della stringa in un booleano con il vecchio trucco doppio non operatore - come hai già indicato sia "true" che "false" diventerebbe vero, ma questo problema scompare se usi "true" e "" (stringa vuota) - così puoi usare Boolean() come per il tuo "terzo tentativo".

tentativo Sesto ...

@{ string IsSet = Model.IsSet ? "true" : "false"; } 

// helper function at the top of your page: 
function bool(strVal) { 
    return strVal === "true"; 
} 

// variable declaration 
var isSet = bool("@(IsSet)"); 

OK, così si finisce con una funzione abbastanza inutile nella parte superiore della pagina, ma mantiene le dichiarazioni delle variabili effettivi ragionevolmente ordinata e se il debug lato client vedrai bool("false") o bool("true").

settimo tentativo ...

non mi piace il passaggio aggiuntivo di creazione del server-side string IsSet = Model.IsSet ? "true" : "false"; in anticipo. Non so sintassi Razor, ma si può dire qualcosa sulla falsariga di:

var isSet = !!"@(Model.IsSet ? "true" : "")"; 
// OR, better: 
var isSet = !!"@(rzrBool(Model.IsSet))"; 
// where rzrBool() is a server-side helper function (that you would create) 
// which returns "true" or "" 

mi aspetterei tutti i miei "tentativi" per lavorare, ma ancora una volta credo che il tuo "primo tentativo" è l'opzione migliore .

+0

A proposito, le parentesi sono davvero necessarie ovunque tu abbia detto '@ (IsSet)', o puoi semplicemente dire '@ IsSet'? Se quest'ultimo è OK, renderebbe ogni variazione più ordinata. – nnnnnn

+0

Innanzitutto, il problema con la formattazione automatica è che non fa nulla quando si ha JavaScript non valido. Lo stesso si applicherebbe se perdessi una parentesi di chiusura da una chiamata di funzione ecc. In secondo luogo, rispondi a tutti l'aspetto lavorabile, tranne il settimo che probabilmente richiederebbe l'uso 'per avvolgere l'intera stringa per evitare problemi con il contenere le virgolette, anche questa opzione sembra sgradevole . Sono d'accordo che il primo è il migliore, ma l'auto-formattazione è troppo importante per rinunciare. Potrei andare per la funzione bool, dato che ho altri punti di vista che fanno cose simili. – musefan

+1

Sospetto che il mio "5b" sia l'opzione migliore per te. Non richiede alcuna funzione aggiuntiva (client o lato server) ed è proprio come il terzo tentativo dopo aver modificato il codice lato server per restituire "true" o stringa vuota anziché "true" o "false". (Per quanto riguarda il mio 7a, sì, dovresti usare le virgolette singole all'esterno per rendere VS felice anche se di nuovo dovrebbe funzionare così com'è.) – nnnnnn

0

ne dite:

@Model.IsSet.ToString().ToLower() 
+0

Non va bene. Suppongo che intendi usare questo diretto nel blocco JavaScript? Se intendi sostituire la prima riga del mio rasoio C# codice, quindi non farà la differenza neanche lì. – musefan

+0

stampa False per me .... forse se aggiungi .ToLower() per false, var something = @ Model.IsSet.ToString(). ToLower(); –

+0

Sì, funzionerebbe, ma come il mio primo tentativo, interrompe la formattazione automatica in VS 2010 – musefan

0
var isSet= @((bool)Model.IsSet?"true":"false"); 
+1

questa è una cattiva risposta. Per prima cosa non ha senso lanciare 'Model.IsSet' su bool perché è già bool. In secondo luogo, se intendi farlo in JavaScript hai ancora lo stesso problema del mio primo tentativo (interruzioni di formattazione automatica) – musefan

10

Nessuna delle versioni mostrate finora (sia nella domanda che nelle risposte) è qualcosa che vorrei utilizzare. Ecco come lo farei:

@model MyViewModel 
<script type="text/javascript"> 
    var isSet = @Html.Raw(Json.Encode(Model.IsSet)); 

    // TODO: use the isSet javascript variable here as a standard boolean value 
</script> 

o se avete bisogno di altre proprietà del modello al fine di essere manipolati con javascript si potrebbe JSON codificare l'intero modello:

@model MyViewModel 
<script type="text/javascript"> 
    var model = @Html.Raw(Json.Encode(Model)); 

    if (model.IsSet) { 
     alert(model.FooBar); 
    } 
</script> 
+0

Bella alternativa, ma questo ancora interrompe la formattazione automatica per JavaScript. Inoltre, appare un errore "La compilazione condizionale è disattivata" ... le parentesi aggiunte risolvono questa parte del problema ... '@ (Html.Raw (Json.Encode (Model.IsSet)))' – musefan

+2

@musefan, Intellisense in Razor, specialmente se mescolato con javascript, fa schifo. È qualcosa che ho smesso di preoccuparmi molto tempo fa. Speriamo che Microsoft lo aggiusterà in qualche versione futura. Emette alcuni avvertimenti che non dovrebbero essere emessi. Personalmente mi concentro sulla scrittura di codice corretto che non sia vulnerabile agli attacchi XSS injection ... e che so funzionerà correttamente in runtime poiché codifica correttamente tutto. Il fatto che VS mi dia degli avvertimenti su un codice perfettamente valido è qualcosa per cui i progettisti di VS dovrebbero essere incolpati, non te stesso come autore di questo codice. –

+0

Questa è una bella alternativa. Sebbene rompa la formattazione automatica, sarebbe solo un problema su una riga all'inizio, senza alcun altro codice lato server mischiato a JavaScript. – nnnnnn

14

Ho appena lottato con la stessa problema per circa un'ora. La mia soluzione finale era equivalente alla seguente.

var IsSet = @(Model.IsSet.ToString().ToLower()); // Inside JavaScript block 

Non richiede codice aggiuntivo.

+2

Questo si interromperà allo stesso modo del primo tentativo. Intellisense non riconoscerà che qualcosa è stato scritto per l'inizializzazione della variabile e mostra una riga rossa ondulata al punto e virgola. –

+0

Perfetto in MVC 4. tks – Gandarez

1

ne dite:

@Ajax.ToJson(Model.IsSet) 
+0

Che cos'è '@ Ajax.ToJson()'? Non compare nel mio intellisense, o in Google – musefan

0

Ecco quello che io uso, all'interno di un blocco javascript:

var someValue; 
@{ var someValue= "someValue= " + Model.SomeValue+ ";"; } 
@someValue 
1
var isSet = /true/i.test('@Model.IsSet'); 
  • linea singola
  • Gestisce la differenza tra il caso.Net e JavaScript
  • Funziona con auto-formattazione (Visual Studio e Visual Studio con ReSharper)
  • Ragionevolmente idiomatica se si ha familiarità con JavaScript regex
  • Abbastanza resistenti agli errori di logica; dovrebbe fare come previsto o lanciare un errore JavaScript (o eventualmente un errore di compilazione Razor).
0

So che questa è una domanda vecchia, ma nessuna delle risposte è particolarmente elegante.

La soluzione più semplice in queste situazioni è semplicemente quella di aggiungere +0 al vostro condizionale. Converte implicitamente il bool in un int, ma poiché il risultato è 0 o 1 viene immediatamente convertito nuovamente dall'istruzione if. Esempio:

// The space is optional 
if (@IsSet +0) { 
    // Do stuff 
} 

Assegnare un valore booleano a una variabile potrebbe essere raggiunto nel modo seguente:

// Note the double (not triple) equals, which performs type conversion 
var isSet = @IsSet+0 == true; 

Il codice funziona, si ottiene linee ondulate rosse, e il Visual Studio formattatore è felice.

Problemi correlati