Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeNameHandling in Newtonsoft requires $type to be the first property? [duplicate]

I have the following method in my web api

public void Put(string id, [FromBody]IContent value) {
    //Do stuff
}

I'm using backbone js to send the following JSON to the server using fiddler the value is null:

{
    "id": "articles/1",
    "heading": "Bar",
    "$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"
}

but if I add the $type property first in the JSON object the deserialization works fine, see:

{
 "$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
  "id": "articles/1",
  "heading": "Bar" 
}

is it possible to configure newtonsoft to check for the $type property anywhere in the object instead of the first property or can I configure backbone so it always adds the $type property first in the JSON object?

like image 968
marcus Avatar asked Mar 22 '13 12:03

marcus


People also ask

What is TypeNameHandling in C#?

This sample uses the TypeNameHandling setting to include type information when serializing JSON and read type information so that the create types are created when deserializing JSON.

What does Jsonconvert DeserializeObject do?

DeserializeObject Method. Deserializes the JSON to a . NET object.

What is JsonProperty C#?

This sample uses JsonPropertyAttribute to change the names of properties when they are serialized to JSON. Types. public class Videogame { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("release_date")] public DateTime ReleaseDate { get; set; } }

What is Jsonserializersettings?

Specifies the settings on a JsonSerializer object. Newtonsoft.Json.


2 Answers

I would very strongly recommend against configuring any serializer (including JSON.NET) to read the object type from the incoming payload. This has historically been the cause of a large number of vulnerabilities in web applications. Instead, change the public entry point to your action to take the actual type as a bound parameter, then delegate to an internal testable method if desired.

like image 174
Levi Avatar answered Sep 28 '22 09:09

Levi


First, AFAIK, the code of Json.NET is optimized to avoid holding the whole object in memory just to read its type. So it's better to place $type as the first property.

Second, you can write your own JsonConverter which reads first to JObject (using Load method), manually reads $type property, gets type from serializer's SerializationBinder, creates the value and populates it from JObject.

Third, regarding security. While Json.NET's $type may sound like a good idea, it's often not. It allows Json.NET to create any object type from any assembly just by writing its type in JSON file. It's better to use custom SerializationBinder with a dictionary which allows only types which you specify. You can find an example in my private framework (it also supports getting values for $type from JsonObjectAttribute):

https://github.com/Athari/Alba.Framework/blob/742ff1aeeb114179a16ca42667781944b26f3815/Alba.Framework/Serialization/DictionarySerializationBinder.cs

(This version uses some methods from other classes, but they're trivial. Later commits made the class more complex.)

like image 24
Athari Avatar answered Sep 28 '22 10:09

Athari