¿Cómo escribo Json sin codificar en mi vista usando Razor?

153

Estoy tratando de escribir un objeto como JSON en mi Asp.Net MVC View usando Razor, así:

<script type="text/javascript">
  var potentialAttendees = @Json.Encode(Model.PotentialAttendees);
</script>

El problema es que en la salida el JSON está codificado y a mi navegador no le gusta. Por ejemplo:

<script type="text/javascript">
    var potentialAttendees = [{&quot;Name&quot;:&quot;Samuel Jack&quot;},];
</script>

¿Cómo consigo que Razor emita JSON sin codificar?

Samuel Jack
fuente

Respuestas:

190

Tú lo haces:

@Html.Raw(Json.Encode(Model.PotentialAttendees))

En versiones anteriores a Beta 2 lo hiciste como:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))
Lorenzo
fuente
3
¿Qué puedo hacer si quiero texto codificado en las propiedades de mis objetos? \, {\ "UrlPart \": \ "TjcolklFX5c \", \ "Title \": \ "When Mama Isn \ u0027t Home \"}, {\ "Por ejemplo. Esto se romperá porque js piensa que el 'está escapando del decalration secuencia nativa de var a = '' mismo va para "" idea de Anny.?
SomeRandomName
@SomeRandomName que puedes usar javascriptserializerpara eso @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))
vikscool
Estamos en 2017, usando MVC 5 y esta respuesta sigue siendo perfecta.
Gabriel Espinoza
Esta respuesta es la única que funciona perfectamente. ¡Gracias!
Jean-Paul
43

Newtonsoft JsonConvert.SerializeObjectno se comporta igual Json.Encodey hacer lo que sugiere @ david-k-egghead te abre a ataques XSS .

Coloque este código en una vista de Razor para ver que el uso Json.Encodees seguro y que Newtonsoft se puede hacer seguro en el contexto de JavaScript, pero no sin algún trabajo adicional.

<script>
    var jsonEncodePotentialAttendees = @Html.Raw(Json.Encode(
        new[] { new { Name = "Samuel Jack</script><script>alert('jsonEncodePotentialAttendees failed XSS test')</script>" } }
    ));
    alert('jsonEncodePotentialAttendees passed XSS test: ' + jsonEncodePotentialAttendees[0].Name);
</script>
<script>
    var safeNewtonsoftPotentialAttendees = JSON.parse(@Html.Raw(HttpUtility.JavaScriptStringEncode(JsonConvert.SerializeObject(
        new[] { new { Name = "Samuel Jack</script><script>alert('safeNewtonsoftPotentialAttendees failed XSS test')</script>" } }), addDoubleQuotes: true)));
    alert('safeNewtonsoftPotentialAttendees passed XSS test: ' + safeNewtonsoftPotentialAttendees[0].Name);
</script>
<script>
    var unsafeNewtonsoftPotentialAttendees = @Html.Raw(JsonConvert.SerializeObject(
        new[] { new { Name = "Samuel Jack</script><script>alert('unsafeNewtonsoftPotentialAttendees failed XSS test')</script>" } }));
    alert('unsafeNewtonsoftPotentialAttendees passed XSS test: ' + unsafeNewtonsoftPotentialAttendees[0].Name);
</script>

Ver también:

Jeremy Cook
fuente
¿Tienes alguna idea cuando agregaron Json.Encode? No sabía que en realidad había una forma segura de insertar json en la página y sé que hice muchas investigaciones al respecto en el pasado.
Chris Marisic
1
Json.Encodeha existido desde que tengo memoria, pero la desventaja es que usa la implementación de Microsoft que genera fechas no estándar (y puede hacer otras cosas molestas). Uso y aliento el uso de Newtonsoft JsonConvert.SerializeObjectcombinado con un escape adecuado porque tiene una mejor salida.
Jeremy Cook
2
Me alegro de haberme desplazado hacia abajo. Inmediatamente vi la respuesta aceptada, esperaba que hubiera una forma segura de hacer esto.
frostymarvelous
La versión HttpUtility.JavaScriptStringEncode también codifica las comillas en el JSON, haciéndolo inválido si se usa directamente en un script [type = 'application / json'], lo cual es una pena.
Pete Kirkham
1
Nota para el yo futuro: El que desea usar es este: @ Html.Raw (Json.Encode ())
Pangamma
12

Usando Newtonsoft

<script type="text/jscript">
  var potentialAttendees  = @(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>
Ravi Ram
fuente
1
Esto es potencialmente vulnerable a las vulnerabilidades XSS que corrige Json.Encode, pero puede anularlo JsonSerializerSettings.StringEscapeHandlingpara habilitar la codificación. stackoverflow.com/a/50336590/6950124
Kevin Secrist