tutorial paso example ejemplo crear consumir c# rest asp.net-web-api

c# - paso - web-api POST cuerpo objeto siempre nulo



web api json c# (16)

Compruebe si el atributo JsonProperty está establecido en los campos que vienen como nulos; podría ser que estén mapeados a diferentes nombres de propiedades json.

Todavía estoy aprendiendo la API web, así que perdónenme si mi pregunta suena estúpida.

Tengo esto en mi StudentController :

public HttpResponseMessage PostStudent([FromBody]Models.Student student) { if (DBManager.createStudent(student) != null) return Request.CreateResponse(HttpStatusCode.Created, student); else return Request.CreateResponse(HttpStatusCode.BadRequest, student); }

Para probar si esto funciona, estoy usando la extensión de Google Chrome "Postman" para construir la solicitud HTTP POST para probarla.

Esta es mi solicitud de POST en bruto:

POST /api/Student HTTP/1.1 Host: localhost:1118 Content-Type: application/json Cache-Control: no-cache {"student": [{"name":"John Doe", "age":18, "country":"United States of America"}]}

Se supone que "student" es un objeto, pero cuando depuro la aplicación, la API recibe el objeto de estudiante pero el contenido siempre es NULL .


En mi caso, el problema era el objeto DateTime que estaba enviando. DateTime un DateTime con "aaaa-MM-dd", y el DateTime requerido por el objeto que estaba mapeando también necesitaba "HH-mm-ss". De modo que agregar "00-00" resolvió el problema (el ítem completo era nulo debido a esto).


Este es un poco antiguo y mi respuesta bajará al último lugar, pero aún así me gustaría compartir mi experiencia.

Intenté cada sugerencia, pero aún tenía el mismo valor "nulo" en un PUT [FromBody].

Finalmente descubrí que todo se trataba del formato de fecha mientras JSON serializaba la propiedad EndDate de mi objeto angular.

No se arrojó ningún error, acaba de recibir un objeto FromBody vacío ...


Estuve buscando una solución a mi problema durante algunos minutos, así que compartiré mi solución.

Su modelo necesita tener un constructor vacío / predeterminado, de lo contrario, el modelo no se puede crear, obviamente. Tenga cuidado al refactorizar. ;)


FromBody es un atributo extraño en el sentido de que los valores POST de entrada deben estar en un formato específico para que el parámetro sea no nulo, cuando no es un tipo primitivo. (estudiante aquí)

  1. Pruebe su solicitud con {"name":"John Doe", "age":18, "country":"United States of America"} como json.
  2. Elimine el atributo [FromBody] y pruebe la solución. Debería funcionar para tipos no primitivos. (estudiante)
  3. Con el atributo [FromBody] , la otra opción es enviar los valores en formato =Value , en lugar de formato key=value . Esto significaría que su valor clave de student debería ser una cadena vacía ...

También hay otras opciones para escribir una carpeta de modelo personalizada para la clase de estudiante y atribuir el parámetro con su carpeta personalizada.


Parece que puede haber muchas causas diferentes de este problema ...

Descubrí que agregar una devolución de llamada OnDeserialized a la clase de modelo provocaba que el parámetro siempre fuera null . Razón exacta desconocida.

using System.Runtime.Serialization; // Validate request [OnDeserialized] // TODO: Causes parameter to be null public void DoAdditionalValidatation() {...}


Paso varias horas con este problema ... :( Los getters y setters son OBLIGATORIOS en la declaración de objetos de parámetros POST. No recomiendo usar objetos de datos simples (cadena, int, ...) ya que requieren un formato de solicitud especial.

[HttpPost] public HttpResponseMessage PostProcedure(EdiconLogFilter filter){ ... }

No funciona cuando:

public class EdiconLogFilter { public string fClientName; public string fUserName; public string fMinutes; public string fLogDate; }

Funciona bien cuando:

public class EdiconLogFilter { public string fClientName { get; set; } public string fUserName { get; set; } public string fMinutes { get; set; } public string fLogDate { get; set; } }


Puede ser útil agregar TRACING al serializador json para que pueda ver qué sucede cuando las cosas van mal.

Defina una implementación de ITraceWriter para mostrar su resultado de depuración como:

class TraceWriter : Newtonsoft.Json.Serialization.ITraceWriter { public TraceLevel LevelFilter { get { return TraceLevel.Error; } } public void Trace(TraceLevel level, string message, Exception ex) { Console.WriteLine("JSON {0} {1}: {2}", level, message, ex); } }

Luego, en su WebApiConfig, haga lo siguiente:

config.Formatters.JsonFormatter.SerializerSettings.TraceWriter = new TraceWriter();

(tal vez envolverlo en #if DEPURADOR)


Quizás para alguien sea útil: verifique los modificadores de acceso para las propiedades de su clase DTO / Modelo, deben ser públicos . En mi caso, durante la refactorización, los objetos internos del dominio se movieron a DTO de la siguiente manera:

// Domain object public class MyDomainObject { public string Name { get; internal set; } public string Info { get; internal set; } } // DTO public class MyDomainObjectDto { public Name { get; internal set; } // <-- The problem is in setter access modifier (and carelessly performed refactoring). public string Info { get; internal set; } }

DTO está siendo pasado finamente al cliente, pero cuando llega el momento de pasar el objeto de vuelta al servidor, solo tenía campos vacíos (valor nulo / predeterminado). La eliminación de "interno" pone las cosas en orden, permitiendo que el mecanismo de deserialización escriba las propiedades del objeto.

public class MyDomainObjectDto { public Name { get; set; } public string Info { get; set; } }


Si cualquiera de los valores del objeto JSON de la solicitud no es del mismo tipo que el esperado por el servicio, entonces el argumento [FromBody] será null .

Por ejemplo, si la propiedad de edad en el json tiene un valor float :

"edad": 18.0

pero el servicio API espera que sea una int

"edad": 18

entonces el student será null . (No se enviarán mensajes de error en la respuesta a menos que no haya una verificación de referencia nula).


Si esto se debe a que la API web 2 se encontró con un problema de deserialización debido a tipos de datos no coincidentes, es posible averiguar dónde falló inspeccionando la secuencia de contenido. Se leerá hasta que aparezca un error, por lo que si lee el contenido como una cadena, debería tener la mitad de atrás de los datos que publicó:

string json = await Request.Content.ReadAsStringAsync();

Repara ese parámetro, y debería hacerlo más adelante la próxima vez (¡o tener éxito si tienes suerte!) ...


Si usa Postman, asegúrese de que:

  • Ha configurado un encabezado "Content-Type" para "application / json"
  • Estás enviando el cuerpo como "crudo"
  • No necesita especificar el nombre del parámetro en ningún lugar si está utilizando [FromBody]

Estaba intentando estúpidamente enviar mi JSON como datos de formulario, duh ...


Solo para agregar mi historial a este hilo. Mi modelo:

public class UserProfileResource { public Guid Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Phone { get; set; } public UserProfileResource() { } }

no se pudo serializar en mi Controlador API, siempre devolviendo nulo. El problema era con Id del tipo Guid : cada vez que pasaba cadena vacía como Id (siendo ingenuo que se convertiría automáticamente a Guid.Empty ) desde mi interfaz recibí el objeto nulo como [FromBody] .

La solución era más clara para

  • pasar valor de Guid válido
  • o cambie Guid a String

También estaba tratando de usar el [FromBody], sin embargo, estaba intentando completar una variable de cadena porque la entrada cambiará y solo tengo que pasarla a un servicio de back-end, pero esto siempre fue nulo.

Post([FromBody]string Input])

Así que cambié la firma del método para usar una clase dinámica y luego convertir eso a cadena

Post(dynamic DynamicClass) { string Input = JsonConvert.SerializeObject(DynamicClass);

Esto funciona bien


Tuve este problema en mi .NET Framework Web API, porque mi modelo existía en un proyecto .NET Standard que hacía referencia a una versión diferente de las anotaciones de datos.

Agregar la línea ReadAsAsync a continuación destacó la causa para mí:

public async Task<HttpResponseMessage> Register(RegistrationDetails registrationDetails) { var regDetails = await Request.Content.ReadAsAsync<RegistrationDetails>();


Yo tuve el mismo problema.

En mi caso, el problema fue en public int? CreditLimitBasedOn { get; set; } public int? CreditLimitBasedOn { get; set; } public int? CreditLimitBasedOn { get; set; } propiedad que tuve.

mi JSON tenía el valor "CreditLimitBasedOn":true cuando debería contener un número entero. Esta propiedad evitó que todo el objeto se deserializara en mi método api.