How do I write unencoded Json to my View using Razor?
Asked Answered
S

3

162

I'm trying to write an object as JSON to my Asp.Net MVC View using Razor, like so:

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

The problem is that in the output the JSON is encoded, and my browser doesn't like it. For example:

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

How do I get Razor to emit unencoded JSON?

Supertonic answered 1/11, 2010 at 20:24 Comment(0)
S
204

You do:

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

In releases earlier than Beta 2 you did it like:

@(new HtmlString(Json.Encode(Model.PotentialAttendees)))
Schematic answered 1/11, 2010 at 20:27 Comment(4)
What can i do if i want some encoded text in my objects properties? \,{\"UrlPart\":\"TjcolklFX5c\",\"Title\":\"When Mama Isn\u0027t Home\"},{\" For example. This will break beacause js thinks the ' is escaping the native string decalration of var a = ' ' same goes for " ". anny idea ?Dubitation
@Dubitation you can use javascriptserializer for that like @Html.Raw(javascriptSerializerObjecct.Serialize(myObject))Tyus
We are in 2017, using MVC 5 and this answer is still perfect!Kentkenta
This answer is the only one that works perfectly. Thanks!Poultryman
I
47

Newtonsoft's JsonConvert.SerializeObject does not behave the same as Json.Encode and doing what @david-k-egghead suggests opens you up to XSS attacks.

Drop this code into a Razor view to see that using Json.Encode is safe, and that Newtonsoft can be made safe in the JavaScript context but is not without some extra work.

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

See also:

Ingham answered 17/4, 2014 at 21:17 Comment(9)
Do you have any idea when they added Json.Encode? I wasn't aware there was actually a safe way to insert json on the page and I know I did alot of research on it in the past.Yorick
Json.Encode has been around as long as I can remember, but the downside is that it uses Microsoft's implementation that outputs non-standard dates (and may do other bothersome things). I use and encourage the use of Newtonsoft's JsonConvert.SerializeObject combined with proper escaping because it has better output.Ingham
Glad I scrolled down. Immediately I saw the accepted answer, I hoped there was a safe way to do this.Projectionist
The HttpUtility.JavaScriptStringEncode version also encodes the quote marks in the JSON, rendering it invalid if used directly in a script[type='application/json'], which is a pity.Sidonie
Note to future self: The one you want to use is this: @Html.Raw(Json.Encode( ))Smaragdine
Is there any way to make sure the Json.Encode handles reference loops properly?Smaragdine
@Smaragdine I would suggest you use JsonConvert and pass JsonSerializerSettings with ReferenceLoopHandling handling set to the value that meets your needs. Not sure what you mean by "properly". Handling something "properly" varies from case to case. So you would need to be more specific about what isn't working and how you wish it would be working.Ingham
Isn't this only unsafe if you can't trust the JSON you are inserting to the page?Mame
@Mame there are two factors, one is trust but the other is malformed HTML. Proper encoding addresses both. Visit this page and search for the word "context" to learn more.Ingham
D
15

Using Newtonsoft

<script type="text/jscript">
  var potentialAttendees  = @(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.PotentialAttendees)))
</script>
Damselfish answered 16/9, 2013 at 15:22 Comment(1)
This is potentially vulnerable to XSS vulnerabilities which Json.Encode fixes, but you can override the JsonSerializerSettings.StringEscapeHandling to enable encoding. https://mcmap.net/q/151891/-where-are-json-encode-or-json-decode-methods-in-mvc-6Toccaratoccata

© 2022 - 2024 — McMap. All rights reserved.