2012-10-11 70 views
15

¿Cómo puede la API web no deserializar un objeto que JSON.Net deserializa?¿Por qué la API Web no deserializará esto pero lo hará JSON.Net?

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

Este es el controlador de API Web:

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

Este es el JSON, capturado por Fiddler y formateado:

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

Una clase de ejemplo que serializa con JSON.Net pero no con un controlador Web API:

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

La API web utiliza JSON.Net, y no estoy usando ningún formateador JSON personalizado, simplemente pasando el JSON a un controlador de API web. ¿Por qué esto no funciona?

EDIT: a lo solicitado, que llamo mi controlador de API Web con este Javascript (jQuery parte de tablas de datos). Tenga en cuenta que estoy seguro de la misma JSON es llegar a mi regulador independientemente porque yo he capturado el paquete HTTP crudo con Fiddler y se aseguró de que es correcto:

"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); 
     } 
    }); 
}, 

La petición HTTP prima sigue:

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

Por favor, publique cómo llama a su método webapi (el código js ajax)! – nemesv

+1

Asegúrese de que su solicitud tenga el encabezado 'Content-Type: application/json' – marcind

+0

@nemesv: Listo. :) –

Respuesta

21

Intente eliminar los atributos [Serializable] de sus clases EditorSubmissionMainView y EditorSubmissionMainViewData.

+0

Eso solucionó el problema. El controlador ahora deserializa el objeto. ¿WTH? :) Irónico, agregué '[Serializable]' en un intento vano de resolver un problema anterior. Todavía no entiendo por qué JSON.Net puede deserializar cuando se usa directamente porque el objeto todavía está etiquetado con '[Serializable]'. ¡Extraño! –

+7

El serializador Json.NET establece de manera predeterminada IgnoreSerializableAttribute en verdadero. En WebAPI, lo configuramos como falso. El motivo por el que aciertas es porque Json.NET ignora las propiedades: "Json.NET ahora detecta los tipos que tienen SerializableAttribute y serializa todos los campos de ese tipo, tanto públicos como privados, e ignora las propiedades" (citado de http: //james.newtonking.com/archive/2012/04/11/json-net-4-5-release-2-serializable-support-and-bug-fixes.aspx) –

+0

@Maggie Ying: cualquier idea sobre esta cuestión : http://stackoverflow.com/questions/20252027/json-net-web-api-serialization-with-derrived-inherited-types – amcdnl

0

Creo que el problema puede ser el uso de "datos" o "id" en su json. Debido a que esto tiene que ir a través de la carpeta de modelo, puede confundirse con la variable "id" en la ruta predeterminada. O bien, puede confundirse con el término genérico "datos" que a menudo se utiliza para describir la carga útil en sí.

Intente cambiar estos nombres y háganos saber si eso lo resuelve.

Cuestiones relacionadas