Les propriétés de paramètre complexes de l’API Web sont toutes nulles

J’ai un appel de service API Web qui met à jour les préférences d’un utilisateur. Malheureusement, lorsque j’appelle cette méthode POST depuis un appel ajax jQuery, les propriétés de l’object paramètre de requête sont toujours nulles (ou les valeurs par défaut), plutôt que ce qui est transmis. Si j’appelle la même méthode exacte à l’aide d’un client REST (j’utilise Postman) , ça marche à merveille. Je ne peux pas comprendre ce que je fais de mal avec cela, mais j’espère que quelqu’un a déjà vu cela auparavant. C’est assez simple …

Voici mon object de requête:

public class PreferenceRequest { [Required] public int UserId; public bool usePopups; public bool useTheme; public int recentCount; public ssortingng[] detailsSections; } 

Voici ma méthode de contrôleur dans la classe UserController:

  public HttpResponseMessage Post([FromBody]PreferenceRequest request) { if (request.systemsUserId > 0) { TheRepository.UpdateUserPreferences(request.UserId, request.usePopups, request.useTheme, request.recentCount, request.detailsSections); return Request.CreateResponse(HttpStatusCode.OK, "Preferences Updated"); } else { return Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, "You must provide User ID"); } } 

Voici mon appel ajax:

 var request = { UserId: userId, usePopups: usePopups, useTheme: useTheme, recentCount: recentCount, detailsSections: details }; $.ajax({ type: "POST", data: request, url: "http://localhost:1111/service/User", success: function (data) { return callback(data); }, error: function (error, statusText) { return callback(error); } }); 

J’ai essayé de définir dataType & contentType sur plusieurs éléments différents (‘json‘, ‘application / json’, etc.), mais les propriétés de l’object de requête sont toujours définies par défaut ou sont nulles. Donc, par exemple, si je passe dans cet object:

 var request = { UserId: 58576, usePopups: false, useTheme: true, recentCount: 10, detailsSections: ['addresses', 'aliases', 'arrests', 'events', 'classifications', 'custody', 'identifiers', 'phone', 'remarks', 'watches'] } 

Je peux voir un object de requête entièrement rempli avec les valeurs valides énumérées ci-dessus. Mais dans le contrôleur API Web, la demande est là, mais les propriétés sont les suivantes:

  UserId: 0, usePopups: false, useTheme: false, recentCount: 0, detailsSections: null 

FYI – Je ne fais AUCUNE page ASP.Net MVC ou ASP.NET avec ce projet, j’utilise simplement l’API Web en tant que service et passe tous les appels à l’aide de jQuery $ .ajax.

Une idée de ce que je fais mal ici? Merci!

UPDATE: Je veux juste noter que j’ai plusieurs méthodes dans ce même projet d’API Web dans d’autres contrôleurs qui font exactement la même chose , et j’appelle exactement de la même manière , et elles fonctionnent parfaitement! J’ai passé la matinée à comparer les différents appels, et il ne semble pas y avoir de différence entre la méthode et les en-têtes, mais cela ne fonctionne tout simplement pas avec cette méthode.

J’ai également essayé de passer à une méthode Put, mais j’obtiens exactement les mêmes résultats: l’object de requête entre, mais ne contient pas les valeurs correctes. Ce qui est frustrant, c’est que j’ai environ 20 classes de contrôleurs dans ce projet, et les postes fonctionnent dans toutes ces …

Cela semble être un problème commun en ce qui concerne Asp.Net WebAPI.
Généralement, la cause des objects nuls est la désérialisation de l’object json dans l’object C #. Malheureusement, il est très difficile de déboguer – et par conséquent de localiser votre problème.
Je préfère simplement envoyer le JSON complet en tant qu’object, puis le désérialiser manuellement. Au moins de cette façon, vous obtenez de vraies erreurs au lieu de NULL.
Si vous modifiez la signature de votre méthode pour accepter un object, utilisez JsonConvert:

 public HttpResponseMessage Post(Object model) { var jsonSsortingng = model.ToSsortingng(); PreferenceRequest result = JsonConvert.DeserializeObject(jsonSsortingng); } 

Peut-être que ça va aider, j’avais le même problème.

Tout fonctionnait bien et, soudainement, toutes les propriétés étaient en défaut.

Après quelques tests rapides, j’ai trouvé que c’était le [Serializable] qui posait problème :

 public IHttpActionResult Post(MyComplexClass myTaskObject) { //MyTaskObject is not null, but every member are (the constructor get called). } 

et voici un extrait de ma classe:

 [Serializable] <-- have to remove that [if it was added for any reason..] public class MyComplexClass() { public MyComplexClass () { ..initiate my variables.. } public string blabla {get;set;} public int intTest {get;set; } 

Je suppose que le problème est que votre contrôleur attend le type de contenu [FromBody], essayez de modifier votre contrôleur en

 public HttpResponseMessage Post(PreferenceRequest request) 

et ajax à

 $.ajax({ type: "POST", data: JSON.ssortingngify(request);, dataType: 'json', contentType: "application/json", url: "http://localhost:1111/service/User", 

En passant, créer un modèle en javascript n’est peut-être pas la meilleure pratique.

En utilisant cette technique publiée par @blorkfish a très bien fonctionné:

 public HttpResponseMessage Post(Object model) { var jsonSsortingng = model.ToSsortingng(); PreferenceRequest result = JsonConvert.DeserializeObject(jsonSsortingng); } 

J’avais un object paramètre, qui avait deux types natifs et deux autres objects en tant que propriétés. Les objects avaient des constructeurs marqués interne et l’appel JsonConvert.DeserializedObject sur le jsonSsortingng donnait l’erreur:

Impossible de trouver un constructeur à utiliser pour le type ChildObjectB. Une classe doit avoir un constructeur par défaut, un constructeur avec arguments ou un constructeur marqué avec l’atsortingbut JsonConstructor.

J’ai changé les constructeurs en public et il remplit maintenant l’object de paramètre lorsque je remplace le paramètre de modèle Object par l’object réel. Merci!

Je sais, c’est un peu tard, mais je viens de rencontrer le même problème. La réponse de @ blorkfish a également fonctionné pour moi, mais m’a amené à une solution différente. L’une des parties de mon object complexe manquait d’un constructeur sans paramètre. Après avoir ajouté ce constructeur, les deux demandes Put et Post ont commencé à fonctionner comme prévu.

Un peu tard pour le parti, mais j’avais le même problème et le correctif déclarait le contentType dans votre appel ajax:

  var settings = { HelpText: $('#help-text').val(), BranchId: $("#branch-select").val(), Department: $('input[name=departmentRadios]:checked').val() }; $.ajax({ url: 'http://localhost:25131/api/test/updatesettings', type: 'POST', data: JSON.ssortingngify(settings), contentType: "application/json;charset=utf-8", success: function (data) { alert('Success'); }, error: function (x, y, z) { alert(x + '\n' + y + '\n' + z); } }); 

Et votre contrôleur API peut être configuré comme suit:

  [System.Web.Http.HttpPost] public IHttpActionResult UpdateSettings([FromBody()] UserSettings settings) { //do stuff with your UserSettings object now return Ok("Successfully updated settings"); } 

J’ai également été confronté à ce problème et après de nombreuses heures consacrées à debbug et à la recherche, le problème n’était pas causé par les atsortingbuts Content-Type ou Type $ Ajax, mais par les valeurs NULL de mon object JSON. Il s’agit d’un problème très grossier, car Le POST ne fait ni une mais corrige une fois les valeurs NULL le POST était bien et jeté nativement à ma classe respuestaComparacion ici le code:

JSON

  respuestaComparacion: { anioRegistro: NULL, --> cannot cast to BOOL claveElector: NULL, --> cannot cast to BOOL apellidoPaterno: true, numeroEmisionCredencial: false, nombre: true, curp: NULL, --> cannot cast to BOOL apellidoMaterno: true, ocr: true } 

Manette

 [Route("Similitud")] [HttpPost] [AllowAnonymous] public IHttpActionResult SimilitudResult([FromBody] RespuestaComparacion req) { var nombre = req.nombre; } 

Classe

 public class RespuestaComparacion { public bool anioRegistro { get; set; } public bool claveElector { get; set; } public bool apellidoPaterno { get; set; } public bool numeroEmisionCredencial { get; set; } public bool nombre { get; set; } public bool curp { get; set; } public bool apellidoMaterno { get; set; } public bool ocr { get; set; } } 

J’espère que cette aide.

Donc, il y a 3 problèmes possibles dont je suis au courant et où la valeur ne lie pas:

  1. pas de ctor public sans paramètre
  2. les propriétés ne sont pas publiques
  3. il existe une erreur de liaison entraînant un ModelState.Valid == false – les problèmes types sont les suivants: types de valeur non compatibles (object json à chaîne, non-guide, etc.)

J’envisage donc si un filtre devrait être appliqué aux appels d’API qui renverrait une erreur si la liaison entraîne une erreur!

Comme cette question me troublait presque une journée de travail hier, je voudrais append quelque chose qui pourrait aider d’autres personnes dans la même situation.

J’ai utilisé Xamarin Studio pour créer mon projet d’api angular et Web. Lors du débogage, l’object passait parfois par null et parfois par un object peuplé. Ce n’est que lorsque j’ai commencé à déboguer mon projet dans Visual Studio que mon object a été renseigné à chaque demande de publication. Cela semble poser un problème lors du débogage dans Xamarin Studio.

Essayez de déboguer dans Visual Studio si vous rencontrez ce problème de paramètre null avec un autre IDE.

Je suis tombé sur le même problème. Le correctif nécessaire était de s’assurer que toutes les propriétés pouvant être sérialisées pour votre classe de parameters JSON avaient bien été obtenues; ensemble; méthodes explicitement définies. Ne comptez pas sur la syntaxe de la propriété auto C #! J’espère que cela sera corrigé dans les versions ultérieures de asp.net.

Aujourd’hui, j’ai le même problème que le vôtre. Lorsque j’envoie une requête POST depuis ajax le contrôleur reçoit un object vide avec les valeurs de propriété Null et par défaut. La méthode est la suivante:

 [HttpPost] public async Task SaveDrawing([FromBody]DrawingModel drawing) { try { await Task.Factory.StartNew(() => { //Logic }); return Ok(); } catch(Exception e) { return BadRequest(); } } 

Mon type de Content-Type était correct et tout le rest était également correct. Après avoir essayé beaucoup de choses, j’ai trouvé que l’envoi de l’object ressemblait à ceci:

 $.ajax({ url: '/DrawingBoard/SaveDrawing', type: 'POST', contentType: 'application/json', data: dataToPost }).done((response) => { }); 

Cela ne fonctionnera pas, mais l’envoyer comme ceci fonctionnera à la place:

 $.ajax({ url: '/DrawingBoard/SaveDrawing', type: 'POST', contentType: 'application/json', data: JSON.ssortingngify(dataToPost) }).done((response) => { }); 

Oui, JSON.ssortingngify() manquant a causé tout le problème, et il n’est pas nécessaire de mettre = ou quoi que ce soit d’autre comme préfixe ou suffixe de JSON.ssortingngify . Après avoir creusé un peu. J’ai trouvé que le format de la charge utile de la demande était complètement différent entre les deux demandes
C’est la charge de la demande avec JSON.ssortingngify

Demander une charge avec JSON.stringify

Et ceci est la charge de la demande sans JSON.ssortingngify

Demander une charge sans JSON.stringify

Et n’oubliez pas, lorsque les choses deviennent magiques et que vous utilisez Google Chrome pour tester votre application Web. Vider le cache et recharger de temps en temps.

J’ai rencontré le même problème, la solution pour moi était de faire en sorte que les types d’atsortingbuts de ma classe correspondent aux atsortingbuts JSON, je veux dire

 Json: "atsortingbute": "true" 

Devrait être traité comme une chaîne et non comme un booléen. Si un problème de ce type se présentait, tous les atsortingbuts situés sous l’atsortingbut défectueux seraient null par défaut.