2011-12-19 12 views
17

Estoy usando el motor de vista ASP.Net MVC 3 Razor.MVC 3 Razor View: generación de JavaScript a partir de un valor de modelo booleano

Tengo un requisito para generar código JavaScript en mi Vista en función de un valor en mi Modelo de Vista. El valor que necesito usar es booleano, para este ejemplo, llamemos al IsSet.

Entonces, lo que quiero hacer es crear un booleano JavaScript basado en este valor que pueda usar en el script más adelante.

Tenga en cuenta que para todos los ejemplos a continuación tengo este trozo de código en la parte superior de mi vista ...

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

NOTA: Todos los ejemplos a continuación son JavaScript.

Primer intento ...

var IsSet = @(IsSet); 

... esto realmente funciona, el problema es que rompe el auto-formateo (CTRL + E, D) en VS 2010 debido al mal formateados JavaScript, como era de esperar, y esto no es aceptable.

Segundo intento ...

var IsSet = "@(IsSet)"; 

... Lo sé, JavaScript es inteligente, que se auto-analizar mi cadena cuando sea necesario. Ooops, se olvidó de que es un tipo de cadena y todo lo que no sea vacío se evalúa como verdadero.

tercer intento ...

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

.... sin duda esto va a funcionar ... pues no, convertir cadena no vacía en true (mala analizador!)

Cuarto intentar ...

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

Finalmente algo que funciona, pero no se ve muy bien para mí.

Utilizaré esto si es necesario, pero en última instancia, mi pregunta es: ¿hay una mejor manera de manejar este tipo de situación? Quizás, el comportamiento no deseado en mi primer intento es algo que Microsoft puede haber pasado por alto?

Si alguien tiene un quinto intento bonito y ordenado para mí, sería bueno.

Lo importante para mí es que el formato automático en VS 2010 no se rompe

Gracias

+0

Tendría que estar de acuerdo con tu primer intento, que parece ser el más natural para mí, ya que no estás codificando y luego lanzando algo que ya era booleano en primer lugar. Utilicé esa técnica mucho a lo largo de mi código Razor/JS y parece funcionar bien, y no he visto ningún problema con el formateo automático, pero sí uso ReSharper, ¡así que tal vez eso lo arregla automáticamente! –

+0

Uso ReSharper y todavía me encuentro con el problema del formato automático, por lo que no estoy seguro de por qué no está abordando problemas de formato. El problema de auto-formateo y uso de mayúsculas ocurre cuando las variables Pascal-casted Razor aparecen en lugares donde el formateador aplica nombres minúsculos, como nombres de etiquetas HTML o código JS (predominantemente camelCase; en particular, el formateador se activa cuando la sangría automática) se produce ... Entonces, Chris, tengo la corazonada de que podría haber tenido un escenario diferente? –

Respuesta

7

Versión 1 es el único de los que votaría incluso si todos funcionaran, porque es el más legible para los humanos.Desafortunadamente no tengo VS en casa, así que no puedo probarlo para ver cuál es el problema del formato automático, pero si es posible, me gustaría ignorar el problema y seguir usando esa versión dado que hay nada realmente incorrecto con el código; solo VS es confuso. (¿Estás diciendo VS está tratando de interpretar todo como JS y así encontrar inválida?)

Pero si quieres algunas otras opciones:

quinto intento ...

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

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

Forzar el valor de cadena en un booleano con el viejo truco de doble no operador: como ya señaló, tanto "verdadero" como "falso" se convertirían en verdaderos, pero este problema desaparece si usa "verdadero" y "" (cadena vacía) - para que pueda usar Boolean() según su "tercer intento".

sexto intento ...

@{ 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, por lo que terminan con una función bastante inútil en la parte superior de la página, pero mantenga las declaraciones de variables reales razonablemente ordenado y si la depuración del lado del cliente verá bool("false") o bool("true").

séptimo intento ...

no me gusta el paso adicional de crear el lado del servidor string IsSet = Model.IsSet ? "true" : "false"; con antelación. No sé la sintaxis Razor, pero puedo decir algo a lo largo de las líneas de:

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 "" 

Yo esperaría que todos mis "intentos" para trabajar, pero de nuevo creo que su "primer intento" es la mejor opción .

+0

Por cierto, ¿los paréntesis son realmente necesarios en todos los lugares donde diga '@ (IsSet)', o puede simplemente decir '@ IsSet'? Si este último está bien, haría que cada variación sea más nítida. – nnnnnn

+0

En primer lugar, el problema con el formateo automático es que simplemente no hace nada cuando tiene JavaScript no válido. Lo mismo se aplicaría si se saltara un corchete de cierre de una llamada de función, etc. En segundo lugar, todas las respuestas parecen factibles, excepto que el séptimo probablemente requiera usar 'para envolver toda la cadena para evitar problemas con contener comillas, también esta opción parece desagradable . Estoy de acuerdo en que el primero es el mejor, pero el formato automático es demasiado importante para darse por vencido. Podría elegir la función bool, ya que tengo otras vistas que hacen cosas similares. – musefan

+1

Sospecho que mi "5b" es la mejor opción para ti. No requiere ninguna función adicional (del lado del cliente o del servidor), y es como su tercer intento una vez que modifica el código del lado del servidor para devolver "verdadero" o cadena vacía en lugar de "verdadero" o "falso". (Con respecto a mi 7a, sí, necesitaría usar comillas simples en el exterior para hacer feliz a VS, aunque de nuevo debería ejecutarse tal cual) – nnnnnn

0

¿Qué tal:

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

No es bueno. Supongo que quieres utilizar este directo en el bloque de JavaScript? Si quieres reemplazar la primera línea de mi afeitadora C# código, entonces tampoco hará la diferencia. – musefan

+0

imprime False para mí .... tal vez si agrega .ToLower() para falso, var algo = @ Model.IsSet.ToString(). ToLower(); –

+0

Sí, funcionaría. Pero como mi primer intento, rompe el formateado automático en VS 2010 – musefan

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

esta es una mala respuesta. Primero, no tiene sentido hacer casting a 'Model.IsSet' porque ya es bool. En segundo lugar, si quiere hacer esto en JavaScript, todavía tiene el mismo problema que mi primer intento (formateos automáticos) – musefan

10

Ninguna de las versiones mostradas hasta el momento (tanto en la pregunta como en las respuestas) es algo que usaría. Así es como yo lo haría:

@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 si necesitaba otras propiedades de su modelo de vista para ser manipulado con javascript que podría JSON codificar todo el modelo:

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

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

Buena alternativa, pero esto aún rompe el formateado automático de JavaScript. Además, tal como está, recibo un error "La compilación condicional está desactivada" ... los paréntesis añadidos resuelven esta parte del problema ... '@ (Html.Raw (Json.Encode (Model.IsSet)));' – musefan

+2

@musefan, Intellisense en Razor, especialmente cuando se mezcla con javascript es una mierda. Es algo de lo que he dejado de preocuparme hace mucho tiempo. Esperemos que Microsoft lo arregle en alguna versión futura. Emite algunas advertencias que no deberían emitirse. Personalmente, me concentro en escribir el código correcto que no es vulnerable a los ataques de inyección XSS ... y que sé que funcionará correctamente en tiempo de ejecución, ya que codifica todo correctamente. El hecho de que VS me dé advertencias sobre algún código perfectamente válido es algo de lo que los diseñadores de VS deberían ser culpados, no usted mismo como el autor de este código. –

+0

Esta es una buena alternativa. Aunque rompe el formateado automático, eso solo sería un problema en la línea al inicio, sin ningún otro código del lado del servidor mezclado con el JavaScript. – nnnnnn

14

acabo luchado con el mismo problema por alrededor de una hora. Mi solución final fue equivalente a la siguiente.

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

Esto no requiere código adicional.

+2

Esto se romperá de la misma manera que el primer intento. Intellisense no reconocerá que algo se escribió para la inicialización de la variable y mostrará una línea roja ondulada en el punto y coma. –

+0

Perfecto en MVC 4. tks – Gandarez

1

¿Qué tal:

@Ajax.ToJson(Model.IsSet) 
+0

¿Qué es '@ Ajax.ToJson()'? No aparece en mi intellisense, o en Google – musefan

0

Aquí es lo que yo uso, dentro de un bloque javascript:

var someValue; 
@{ var someValue= "someValue= " + Model.SomeValue+ ";"; } 
@someValue 
1
var isSet = /true/i.test('@Model.IsSet'); 
  • sola línea
  • se encarga de la diferencia entre el caso.Net y JavaScript
  • Funciona con el formato automático (Visual Studio y Visual Studio con ReSharper)
  • Razonablemente idiomática si está familiarizado con el lenguaje Java expresiones regulares
  • bastante resistente a los errores de lógica; debería hacer lo previsto o lanzar un error de JavaScript (o posiblemente un error de compilación de Razor).
0

Sé que esta es una pregunta antigua, pero ninguna de las respuestas es particularmente elegante.

La solución más simple en estas situaciones es simplemente anexar +0 a su condicional. Esto convierte implícitamente el bool en un int, pero como el resultado es 0 o 1, la sentencia if la vuelve a convertir inmediatamente. Ejemplo:

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

asignación de un valor a una variable booleana se puede lograr de la siguiente manera:

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

El código funciona, no se obtienen líneas onduladas de color rojo, y el Estudio Visual formateador es feliz.

Cuestiones relacionadas