问题
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?
回答1:
This will work in backbone, but I don't know if every browser will behave the same. There's no guarantee, basically, that every browser will keep the items in the order which they are added.
MyModel = Backbone.Model.extend({
// ...
toJSON: function(){
// build the "$type" as the first parameter
var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
// get the rest of the data
_.extend(json, Backbone.Model.prototype.toJSON.call(this));
// send it back, and hope it's in the right order
return json;
}
});
You're better of getting NewtonSoft's JSON deserializer to work without needing it in a specific position, though. Hopefully that will be possible.
回答2:
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.
回答3:
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.)
回答4:
I had kind of the same question apparently, and someone found an answer. Not sure whats the appropriate way to share an answer and give him ALL the credit, but this is the link: Newtonsoft JSON.net deserialization error where fields in JSON change order
and this is the guy: https://stackoverflow.com/users/3744182/dbc
来源:https://stackoverflow.com/questions/15570510/typenamehandling-in-newtonsoft-requires-type-to-be-the-first-property