Como escrevo Json não codificado no meu View usando o Razor?

153

Estou tentando escrever um objeto como JSON no meu Asp.Net MVC View usando o Razor, assim:

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

O problema é que, na saída, o JSON é codificado e meu navegador não gosta. Por exemplo:

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

Como faço para o Razor emitir JSON não codificado?

Samuel Jack
fonte

Respostas:

190

Você faz:

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

Nas versões anteriores à Beta 2, você fazia o seguinte:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))
Lorenzo
fonte
3
O que posso fazer se quiser um texto codificado nas propriedades dos meus objetos? \, {\ "UrlPart \": \ "TjcolklFX5c \", \ "Title \": \ "Quando a Mama não estiver na casa \"}, {\ "Por exemplo. Isso quebrará porque você acha que está escapando do ' decalração de string nativa de var a = '' o mesmo vale para "". qualquer idéia?
SomeRandomName 20/02
@SomeRandomName que você pode usar javascriptserializerpara isso, como @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))
vikscool
Estamos em 2017, usando o MVC 5 e essa resposta ainda é perfeita!
Gabriel Espinoza
Essa resposta é a única que funciona perfeitamente. Obrigado!
Jean-Paul
43

O Newtonsoft's JsonConvert.SerializeObjectnão se comporta da mesma maneira Json.Encodeque o @ david-k-egghead sugere e abre os ataques XSS .

Coloque esse código em uma visualização do Razor para ver se o uso Json.Encodeé seguro e que a Newtonsoft pode ser protegida no contexto JavaScript, mas não sem trabalho extra.

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

Veja também:

Jeremy Cook
fonte
Você tem alguma idéia de quando eles adicionaram o Json.Encode? Eu não sabia que havia uma maneira segura de inserir o json na página e sei que fiz muita pesquisa sobre isso no passado.
Chris Marisic 07/07
1
Json.Encodeexiste há tanto tempo quanto me lembro, mas a desvantagem é que ele usa a implementação da Microsoft que gera datas fora do padrão (e pode fazer outras coisas incômodas). Eu uso e incentivo o uso do Newtonsoft JsonConvert.SerializeObjectcombinado com o escape apropriado, porque ele tem uma saída melhor.
Jeremy Cook
2
Ainda bem que rolei para baixo. Imediatamente vi a resposta aceita, esperava que houvesse uma maneira segura de fazer isso.
Frostymarvelous 29/07
A versão HttpUtility.JavaScriptStringEncode também codifica as aspas no JSON, tornando-a inválida se usada diretamente em um script [type = 'application / json'], que é uma pena.
Pete Kirkham #
1
Nota para o próprio futuro: O que você quer usar é esta: @ 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
fonte
1
Isso é potencialmente vulnerável às vulnerabilidades XSS que o Json.Encode corrige, mas você pode substituir o JsonSerializerSettings.StringEscapeHandlingpara ativar a codificação. stackoverflow.com/a/50336590/6950124
Kevin Secrist