6

Mam następujące metody w moim Web API

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

Używam backbone.js wysłać następujące JSON do serwera przy użyciu Skrzypek wartość jest null:

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

ale jeśli dodam właściwość $ typ pierwszy w JSON object deserializacji działa poprawnie, zobacz:

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

możliwe jest skonfigurowanie newtonsoft celu sprawdzenia $ type salo rty w dowolnym miejscu obiektu zamiast pierwszej właściwości lub czy mogę skonfigurować szkielet, aby zawsze najpierw dodawać właściwość $type w obiekcie JSON?

+0

Spójrz na odpowiedzi @ Leviego, on jest facetem bezpieczeństwo dla zespołu internetowego. – RickAndMSFT

+1

To jest kompletnie szalone, że działa w ten sposób we wbudowanych systemach JSON.NET i Microsoft ... W wielu bibliotekach JSON, takich jak Jackson w JAVA, NIE jest zagwarantowane, że mapa (którą możesz zbudować w Jackson) jest uporządkowana . W rzeczywistości jest to mapa, a zatem żadne zamówienie nie jest utrzymywane. Nie masz więc żadnej kontroli nad tym, gdzie pojawi się typ $ lub typ __type w JSON. Czasami to pierwszy i działa, czasami nie. W związku z tym niemożliwe jest wyśledzenie tej funkcji ... – Ted

Odpowiedz

1

To będzie działać w kręgosłup, ale nie wiem, czy każda przeglądarka będzie zachowywać się tak samo. Nie ma żadnej gwarancji, w zasadzie, że każda przeglądarka będzie przechowywać elementy w kolejności, w której są dodawane.


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


}); 

Lepiej uzyskać deserializator JSON NewtonSoft, aby działał bez potrzeby w określonej pozycji. Mam nadzieję, że będzie to możliwe.

+0

która działała całkiem nieźle, właściwość $ type już istnieje w modelu szkieletowym, więc możliwe jest uzyskanie "BrickPile.Samples.Models.Article, BrickPile.Samples" z aktualny model zamiast sztywnego kodu? – Marcus

+1

Domyślam się, że this.get ("$ type") zadziała – Marcus

+0

Borth DataContractSerializer (Microsoft), a json.net WYMAGA, że typ $ (lub __type w MS) jest pierwszą właściwością, w przeciwnym razie zakończy się niepowodzeniem. Dlaczego jest to w ten sposób całkowicie niezrozumiałe, ale tak właśnie jest ... – Ted

3

Zdecydowanie zaleca się, aby nie konfigurować żadnego serializera (w tym JSON.NET), aby odczytać typ obiektu z przychodzącego ładunku. W przeszłości było to przyczyną wielu luk w aplikacjach internetowych. Zamiast tego zmień publiczny punkt wejścia na działanie, aby przyjąć rzeczywisty typ jako powiązany parametr, a następnie w razie potrzeby przekazuj go do wewnętrznej, testowalnej metody.

+0

Mój problem polega na tym, że nie znam właściwego typu, jedyne co wiem to to, że implementuje interfejs IContent. Mogę również powiedzieć, że nie jest to publiczny interfejs API, wymaga on uwierzytelnienia. – Marcus

3

Po pierwsze, AFAIK, kod Json.NET jest zoptymalizowany, aby uniknąć trzymania całego obiektu w pamięci tylko po to, aby przeczytać jego typ. Więc lepiej jest umieścić $type jako pierwszą właściwość.

Po drugie, można napisać własny JsonConverter który odczytuje pierwszy JObject (stosując metodę Load), ręcznie czyta $type nieruchomości, dostaje od typu serializer'S SerializationBinder tworzy wartość i wypełnia je od JObject.

Po trzecie, dotyczące bezpieczeństwa. Chociaż Json.NET $type może brzmieć jak dobry pomysł, często nie jest. To pozwala Json.NET stworzyć dowolny typ obiektu z dowolny zestaw po prostu pisząc jego typ w pliku JSON. Lepiej używać niestandardowego SerializationBinder ze słownikiem, który pozwala tylko na określone typy. Można znaleźć przykład w moim prywatnym ram (obsługuje również wartości otrzymujesz za $type z JsonObjectAttribute):

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

(Wersja ta wykorzystuje kilka metod z innych klas, ale są one trywialne Później zobowiązuje uczynił. klasa bardziej skomplikowana.)

+0

Dzięki za odpowiedź, zajrzę do Twojego kodu! – Marcus