2012-10-11 12 views
15

Wie kann die Web-API ein Objekt, das JSON.Net deserialisiert, nicht deserialisieren?Warum wird die Web-API dies nicht deserialisieren, sondern JSON.Net?

Visual Studio showing Web API's attempt as all nulls but JSON.Net's properly populated

Dies ist der Web API Controller:

public void Put(EditorSubmissionMainView ajaxSubmission) { 
// ajaxSubmission: EditorSubmissionMainView with all values ('data' also == null) 

    string json = "{\"id\":\"row_1377\",\"data\":{\"ROTATION\":\"1\",\"EQUIPMENT\":[{\"id\":\"6\"},{\"id\":\"8\"}],\"NOTES\":\"\"}}"; 

    EditorSubmissionMainView foo = Newtonsoft.Json.JsonConvert.DeserializeObject<EditorSubmissionMainView>(json) as EditorSubmissionMainView; 
// foo is a EditorSubmissionMainView but properly deserialized. 
} 

Dies ist der JSON- durch Fiedler erfasst und formatiert:

{ 
    "id": "row_1377", 
    "data": { 
     "ROTATION": "1", 
     "EQUIPMENT": [{ 
      "id": "6" 
     }, 
     { 
      "id": "8" 
     }], 
     "NOTES": "" 
    } 
} 

Ein Beispiel der Klasse, die mit serialisiert JSON.Net aber nicht mit einem Web-API-Controller:

[Serializable] 
public class EditorSubmissionMainView 
{ 
    public string id { get; set; } 
    public EditorSubmissionMainViewData data { get; set; } 
} 

[Serializable] 
public class EditorSubmissionMainViewData 
{ 
    [JsonProperty("ROTATION")] 
    public int? rotation { get; set; } // Same problem if everything is a string 

    [JsonProperty("EQUIPMENT")] 
    public ICollection<Dictionary<string, int?>> equipment { get; set; } 

    [JsonProperty("NOTES")] 
    public string notes { get; set; } 
} 

Die Web-API verwendet JSON.Net, und ich verwende keine benutzerdefinierten JSON-Formatierer, sondern übergebe den JSON nur an einen Web-API-Controller. Warum funktioniert das nicht?

EDIT: Wie gewünscht, rufe ich meine Web-API-Controller mit diesem Javascript (Teil von JQuery DataTables). Beachten Sie, dass ich sicher bin, das gleiche JSON mein Controller wird immer unabhängig, weil ich das rohe HTTP-Paket mit Fiddler aufgenommen haben und dafür gesorgt, dass es richtig ist:

"ajaxUrl": { 
    "create": "POST @Url.Content("~/API/MainView")", 
    "edit": "PUT @Url.Content("~/API/MainView")", 
    "remove": "DELETE @Url.Content("~/API/MainView")" 
}, 

"ajax": function (method, url, data, successCallback, errorCallback) { 
    $.ajax({ 
     "type": method, 
     "url": url, 
     "data": JSON.stringify(data), // Requires IE8+ 
     "contentType": "application/json", 
     "dataType": "json", 
     "success": function (json) { 
      successCallback(json); 
     }, 
     "error": function (xhr, error, thrown) { 
      errorCallback(xhr, error, thrown); 
     } 
    }); 
}, 

Die rohe HTTP-Anforderung folgt:

PUT http://localhost:53367/API/MainView HTTP/1.1 
x-requested-with: XMLHttpRequest 
Accept-Language: en-us 
Referer: http://localhost:53367/Manage/MainView 
Accept: application/json, text/javascript, */*; q=0.01 
Content-Type: application/json 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) 
Host: localhost:53367 
Content-Length: 306 
Connection: Keep-Alive 
Pragma: no-cache 
Cookie: ASP.NET_SessionId=wqsghjrol20cszrxfzdm0qo4 

{"id":"row_1377","data":{"ROTATION":"1","EQUIPMENT":[{"id":"6"},{"id":"8"}],"NOTES":""}} 
+0

Bitte posten Sie wie Sie Ihre Webapi-Methode (den Js Ajax-Code) aufrufen! – nemesv

+1

Stellen Sie sicher, dass Ihre Anfrage den Header "Content-Type: application/json" hat – marcind

+0

@nemesv: Fertig. :) –

Antwort

21

Versuchen Sie, die [Serializable] -Attribute aus den Klassen EditorSubmissionMainView und EditorSubmissionMainViewData zu entfernen.

+0

Das behebt das Problem. Der Controller deserialisiert nun das Objekt. WTH? :) Ironischerweise fügte ich '[Serializable]' in einem vergeblichen Versuch hinzu, ein früheres Problem zu lösen. Ich verstehe immer noch nicht, warum JSON.Net bei direkter Verwendung deserialisieren kann, weil das Objekt immer noch mit '[Serializable]' getaggt ist. Seltsam! –

+7

Json.NET Serializer standardmäßig setzen Sie das IgnoreSerializableAttribute auf True. In WebAPI setzen wir das auf false. Der Grund, warum Sie dieses Problem haben, ist, weil Json.NET Eigenschaften ignoriert: "Json.NET erkennt jetzt Typen, die das SerializableAttribute haben und serialisiert alle Felder dieses Typs, sowohl öffentliche als auch private, und ignoriert die Eigenschaften" (zitiert von http: //james.newtonking.com/archive/2012/04/11/json-net-4-5-release-2-serializable-support-and-bug-fixes.aspx) –

+0

@maggie Ying - Irgendwelche Ideen zu dieser Frage : http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types – amcdnl

0

Ich denke, das Problem kann die Verwendung von "Daten" oder "ID" in Ihrem JSON sein. Da dies durch den Modellordner gehen muss, kann es durch die Variable "id" in der Standardroute verwechselt werden. Oder es wird durch den allgemeinen Begriff "Daten" verwirrt, der oft verwendet wird, um die Nutzlast selbst zu beschreiben.

Versuchen Sie, diese Namen zu ändern und lassen Sie uns wissen, wenn das löst.

Verwandte Themen