Le paramètre de publication est toujours nul

197

Depuis la mise à niveau vers RC pour WebAPI, j'ai un problème étrange lors de l'appel de POST sur mon WebAPI. Je suis même revenu à la version de base générée sur un nouveau projet. Alors:

public void Post(string value)
{
}

et appeler de Fiddler:

Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29

Body:
{
    "value": "test"
}

Lorsque je débogue, la chaîne "value" n'est jamais affectée à. C'est toujours NULL. Quelqu'un a ce problème?

(J'ai d'abord vu le problème avec un type plus complexe)

Le problème n'est pas uniquement lié à ASP.NET MVC 4, le même problème se produit pour un nouveau projet ASP.NET MVC 3 après l'installation de RC

ianrathbone
la source
Juste pour ajouter au problème - ce n'est pas exclusif à JSON, cela arrive aussi avec XML.
ianrathbone
3
Je me bats avec cela depuis deux jours et après avoir lu tous les articles que j'ai pu trouver à ce sujet, il s'est avéré être aussi simple que de formater correctement la chaîne JSON dans WebRequest: les données doivent commencer et se terminer par des guillemets doubles et si vous utilisez des guillemets simples dans toutes vos données json, tout fonctionne bien.
Gineer

Réponses:

101

Comme vous n'avez qu'un seul paramètre, vous pouvez essayer de le décorer avec l' [FromBody]attribut, ou changer la méthode pour accepter un DTO avec une valeur en tant que propriété, comme je l'ai suggéré ici: Liaison de paramètres MVC4 RC WebApi

MISE À JOUR: Le site officiel ASP.NET a été mis à jour aujourd'hui avec une excellente explication: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 1

En résumé, lors de l'envoi d'un seul type simple dans le corps, envoyez uniquement la valeur préfixée par un signe égal (=), par exemple body:

=test

Jim Harte
la source
9
J'ai donné un tourbillon au [FromBody] mais cela n'a pas changé
ianrathbone
11
Passez juste la valeur (c'est-à-dire pas en tant qu'objet JSON) et cela devrait fonctionner, selon blogs.msdn.com/b/jmstall/archive/2012/04/16/…
Jim Harte
8
L'appendice =en face n'a jamais fonctionné pour moi, jusqu'à ce que je suive les conseils de Jim dans son commentaire (pas en tant qu'objet JSON) et que cela fonctionne. C'est la clé! Je n'aime vraiment pas à quel point WebAPI est difficile.
gitsitgo
16
C'est tellement stupide et ennuyeux que je ne sais pas s'il faut voter contre ou contre la réponse qui m'a aidé à résoudre mon problème ... Pourquoi diable doit-il être dans ce format? (Désolé pour l'attitude, juste perdu trop de temps à ce sujet, et cela n'a aucun sens ... :(). Vous devez vraiment ajouter un support pour le format que les gens s'attendent à ce qu'il accepte.
gdoron soutient Monica
6
Merci! Comment diable devrions-nous savoir que nous devons supprimer le nom du paramètre lors de l'envoi d'un seul paramètre? Quel cerveau d'oiseau a eu cette idée?
Jenny O'Reilly
104

Je me suis gratté la tête aujourd'hui.

Ma solution est de changer le [FromBody]en a HttpRequestMessage, essentiellement en remontant la pile HTTP.

Dans mon cas, j'envoie des données à travers le fil qui est zippé json qui est ensuite base64'd. Tout cela à partir d'une application Android.

La signature originale de mon point de terminaison Web ressemblait à ceci (en utilisant [FromBody]):

Mon point de terminaison d'origine

Mon correctif pour ce problème était de revenir à l'utilisation d'un HttpRequestMessagepour la signature de mon point de terminaison.

entrez la description de l'image ici

Vous pouvez ensuite accéder aux données de publication à l'aide de cette ligne de code:

entrez la description de l'image ici

Cela fonctionne et vous permet d'accéder aux données brutes des messages intacts. Vous n'avez pas besoin de jouer avec le violoneux en mettant un signe = au début de votre chaîne ou en changeant le type de contenu.

En passant, j'ai d'abord essayé de suivre l'une des réponses ci-dessus qui consistait à changer le type de contenu en: "Content-Type: application / x-www-form-urlencoded". Pour les données brutes, c'est un mauvais conseil car il supprime les caractères +.

Donc une chaîne base64 qui commence comme ceci: "MQ0AAB + LCAAAAAA" finit comme ceci "MQ0AAB LCAAAAAA"! Pas ce que tu veux.

Un autre avantage de l'utilisation HttpRequestMessageest que vous avez accès à tous les en-têtes http depuis votre point de terminaison.

Ocean Airdrop
la source
6
Excellente solution ... m'a pris 9 heures pour trouver cela, trié mon problème après avoir supprimé la valeur de la chaîne [FromBody] et l'ai remplacé par HttpRequestMessage
Kev
1
Fonctionne comme un charme! mais n'y a-t-il pas un moyen d'utiliser un type de paramètre réel d'un certain objet? par exemple, paramètre de type Ordre pour une méthode API Web?
Ron Nuni
7
Juste une remarque, vous n'avez pas besoin HttpRequestMessage requestde la signature de méthode, car vous l'avez déjà déjà. Dans le corps de la méthode, il est accessible sur l' Requestobjet. par exempleRequest.Content.ReadAsStringAsync().Result;
Morvael
Ce problème est généralement dû au fait que votre objet JSON est incorrect. J'ai trouvé que c'est toujours parce que le constructeur a un type invalide et Json ne sait pas comment le convertir 'Like a Guid en chaîne. Donc, ajoutez le convertisseur via les paramètres ou ajoutez un constructeur vide et vous n'avez pas besoin de revenir à l'ancien code comme celui-ci.
Nick Turner
Le moyen le plus simple consiste à basculer l'objet vers une chaîne, puis à essayer de le convertir et vous verrez l'erreur JSON. Vérifiez également que vous êtes des en-têtes.
Nick Turner
71

Je viens d'avoir ce problème avec Fiddler. Le problème était que je n'avais pas précisé Content-Type.

Essayez d'inclure un en-tête pour Content-Typedans votre demande POST.

Content-Type: application/x-www-form-urlencoded

Alternativement, selon les commentaires ci-dessous, vous devrez peut-être inclure un en-tête JSON

Content-Type: application/json
Kirk Broadhurst
la source
11
J'ai eu un problème similaire, sauf que j'avais besoin de définir le type de contenu: application / json
dvallejo
2
Comme spécifié dans l'article - j'avais déjà ajouté Content-Type: application / json
ianrathbone
2
application / x-www-form-urlencoded ne fonctionnait pas pour moi, Content-Type: application / json l'a fait.
liang
1
Quel que soit le type de contenu, si vous n'avez qu'un seul paramètre, vous devez envoyer uniquement la valeur sans le nom du paramètre dans le corps de la demande. Donc id = 13 ne fonctionnera pas. Vous devez en envoyer 13 seul. Voir la réponse de Jim.
Jenny O'Reilly
J'ai dû utiliser contentType: "application/x-www-form-urlencoded; charset=UTF-8", pour un exemple complet, voir Complete Cient and Server
RyBolt
57

J'ai également rencontré ce problème, et voici comment j'ai résolu mon problème

code webapi:

public void Post([FromBody] dynamic data)
{
    string value = data.value;
    /* do stuff */
}

code client:

$.post( "webapi/address", { value: "some value" } );
George
la source
1
Cela fonctionne si le client envoie du JSON. Si j'envoie une valeur simple telle que la chaîne some value, alors dataest nulle.
brianestey
facile, changez votre code client pour renvoyer un objet js.
George
Excellent et propre moyen d'obtenir des données de JSON
Wouter Vanherck
Si vous envoyez json, var json = JsonConvert.SerializeObject (data);
dvallejo
41

J'utilisais Postmanet je faisais la même erreur .. en passant l' valueobjet as json au lieu de la chaîne

{
    "value": "test"
}

Clairement, celui ci-dessus est incorrect lorsque le paramètre api est de type chaîne.

Donc, passez simplement la chaîne entre guillemets dans le corps de l'API:

"test"
JerryGoyal
la source
2
C'était mon problème, et probablement la vraie solution à la question. Une chaîne codée JSON a des guillemets
Kyle W
1
J'ai également rencontré ce problème sur Postman. Il s'avère que j'ai choisi à tort "form-data" au lieu de "raw" pour Body lorsque le Content-Type est défini sur application / json. Vous pouvez vous référer aux captures d'écran de zzyykk123456 sur les problèmes d'aspnet Github: github.com/aspnet/Home/issues/2202
Chun Lin
Cela a fonctionné pour moi. En utilisant Swagger (swashbuckle), je dois définir le type de contenu: application / json et utiliser des guillemets doubles.
John Henckel
1
Exactement mon problème, mais je dois noter que dans les demandes Ajax, vous devez faire «données: JSON.stringify (« YourString »)»
Amir Hossein Ahmadi
1
@AmirHosseinAhmadi Je viens de rencontrer cela sur ajax et j'ai vu que l'utilisation JSON.stringifyme faisait [frombody]être null. Après avoir défini le champ de données sur une valeur de chaîne (c'est-à-dire une chaîne json), cela a fonctionné.
Nexaspx
19

Essayez de créer une classe pour servir de modèle de données, puis envoyez un objet JSON avec des propriétés correspondant aux propriétés de votre classe de modèle de données. (Remarque: j'ai testé cela et cela fonctionne avec le plus récent MVC 4 RC 2012 que je viens de télécharger aujourd'hui).

public HttpResponseMessage Post(ValueModel model)
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, "Value Recieved: " + model.Value);
}

public class ValueModel
{
    public string Value { get; set; }
}

L'objet JSON ci-dessous est envoyé dans le corps HTTP-POST, le type de contenu est application / json

{ "value": "In MVC4 Beta you could map to simple types like string, but testing with RC 2012 I have only been able to map to DataModels and only JSON (application/json) and url-encoded (application/x-www-form-urlencoded body formats have worked. XML is not working for some reason" }

Je crois que la raison pour laquelle vous devez créer une classe de modèle de données est que les valeurs simples sont supposées provenir des paramètres url et qu'une seule valeur complexe est supposée provenir du corps. Ils ont les attributs [FromBody]et [FromUrl], mais l'utilisation [FromBody] string valuen'a toujours pas fonctionné pour moi. On dirait qu'ils travaillent toujours sur beaucoup de bugs, donc je suis sûr que cela va changer à l'avenir.

Edit: Got XML pour fonctionner dans le corps. Le sérialiseur XML par défaut a été remplacé par DataContractSerializer au lieu de XmlSerializer. Mettre la ligne suivante dans mon fichier Global.asax a résolu ce problème ( référence )

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Despertar
la source
cela a fonctionné pour moi avec request.ContentType = "application / json; charset = UTF-8";
Arvind Krmar
15

Après quelques essais, je pense que le comportement par défaut est correct et qu'il n'y a rien à pirater.

La seule astuce est: si votre argument de méthode post est stringcomme ci-dessous, vous devez envoyer une chaîne simple avec des guillemets doubles dans le corps (lorsque vous utilisez ajax ou postman), par exemple,

//send "{\"a\":1}" in body to me, note the outer double quotes
[HttpPost("api1")]
public String PostMethod1([FromBody]string value)
{
    return "received " + value; //  "received {\"a\":1}"
}

Sinon, si vous envoyez une chaîne json dans le corps du message sans guillemets externes et sans guillemets internes échappés, elle doit pouvoir être analysée dans la classe du modèle (le type d'argument), par exemple,{"a":1, "b":2}

public class MyPoco{
    public int a;
    public int b;
}

//send {"a":1, "b":2} in body to me
[HttpPost("api2")]
public String PostMethod2([FromBody]MyPoco value)
{
    return "received " + value.ToString();  //"received your_namespace+MyPoco"
}
Léon
la source
11

Je cherchais une solution à ce problème depuis quelques minutes maintenant, je vais donc partager ma solution.

Si vous postez un modèle, votre modèle doit avoir un constructeur vide / par défaut, sinon le modèle ne peut pas être créé, évidemment. Soyez prudent lors de la refactorisation. ;)

chrjs
la source
Le refactoring est exactement ce qui m'a mordu ici, merci pour le conseil!
Alan
10

Cela a fonctionné pour moi:

  1. Créez une classe C # DTO, avec une propriété pour chaque attribut que vous souhaitez passer de jQuery / Ajax

    public class EntityData
    {
        public string Attr1 { get; set; }
        public string Attr2 { get; set; }
    }
  2. Définissez la méthode de l'API Web:

    [HttpPost()]
    public JObject AddNewEntity([FromBody] EntityData entityData)
    {
  3. Appelez l'API Web en tant que telle:

    var entityData = {
        "attr1": "value1",
        "attr2": "value2"
    };
    
    $.ajax({
        type: "POST",
        url: "/api/YOURCONTROLLER/addnewentity",
        async: true,
        cache: false,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            ...
        }
    });
BigMan73
la source
Merci d'avoir posté ceci, j'ai essayé de nombreux échantillons mais cela a fonctionné pour moi!
Satbir
10

Pour ceux qui ont le même problème avec Swagger ou Postman que moi, si vous passez un attribut simple sous forme de chaîne dans un message, même avec le "ContentType" spécifié, vous obtiendrez toujours une valeur nulle.

Passer juste:

MyValue

Va entrer dans le contrôleur comme nul.

Mais si vous réussissez:

"MyValue"

La valeur ira bien.

Les citations ont fait la différence ici. Bien sûr, cela ne concerne que Swagger et Postman. Par exemple, dans une application Frontend utilisant Angular, cela devrait être résolu automatiquement par le framework.

dvc.junior
la source
6

J'ai eu le même problème et j'ai découvert qu'en changeant le type de contenu en "application / json", je n'ai pas résolu le problème. Cependant, "application / json; charset = utf-8" a fonctionné.

byobgyn
la source
Oui, l'API Web ne désérialise pas sans charset = utf-8. blog.codenamed.nl/2015/05/12/…
Sam Rueby
4

J'ai eu un problème similaire où l'objet de demande pour ma méthode d'API Web était toujours nul. J'ai remarqué que puisque le nom de l'action du contrôleur était préfixé avec "Get", l'API Web a traité cela comme un HTTP GET plutôt que comme un POST. Après avoir renommé l'action du contrôleur, cela fonctionne maintenant comme prévu.

Richard Pursehouse
la source
3

Avec Angular, j'ai pu transmettre des données dans ce format:

 data: '=' + JSON.stringify({ u: $scope.usrname1, p: $scope.pwd1 }),
 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }

Et dans Web API Controler:

    [HttpPost]
    public Hashtable Post([FromBody]string jsonString)
    {
        IDictionary<string, string> data = JsonConvert.DeserializeObject<IDictionary<string, string>>(jsonString);
        string username = data["u"];
        string pwd = data["p"];
   ......

Alternativement, je pourrais également publier des données JSON comme ceci:

    data: { PaintingId: 1, Title: "Animal show", Price: 10.50 } 

Et, dans le contrôleur, acceptez un type de classe comme celui-ci:

    [HttpPost]
    public string POST(Models.PostModel pm)
    {

     ....
    }

Dans les deux cas, si vous avez une classe publique établie dans l'API, postez JSON, sinon postez '=' + JSON.stringify ({..: ..., ..: ...})

Yogi
la source
3

Dans mon cas, le problème était que le paramètre était une chaîne et non un objet, j'ai changé le paramètre pour être JObject de Newsoft.Json et cela fonctionne.

syb
la source
2

Ajout d'une ligne

        ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());

à la fin de la fonction protected void Application_Start()dans Global.asax.cs a résolu un problème similaire pour moi dans ASP.NET MVC3.

Sergey Kudriavtsev
la source
Merci pour l'aide mais malheureusement cela n'a pas aidé. Je vais garder la ligne pour le moment car cela peut aider de toute façon!
ianrathbone
Juste pour ajouter les mêmes problèmes se produisent lorsque je poste XML
ianrathbone
2

Si vous utilisez un DataContractSerializer pour votre formateur Xml ou JSON Formatter, vous devez vous en débarrasser. J'avais ceci dans mon fichier WebApiConfig:

public static void Register(HttpConfiguration config)
{
     config.Routes.MapHttpRoute(
           name: "DefaultApi",
           routeTemplate: "api/{controller}/{id}",
           defaults: new { id = RouteParameter.Optional }
     );    

     var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
     jsonFormatter.UseDataContractJsonSerializer = true;
}

Je commente simplement jsonFormatter.UseDataContractJsonSerializer = true;et mon paramètre d'entrée n'est plus nul. Merci à 'Despertar' de m'avoir donné un indice.

Amir Chatrbahr
la source
2

Si vous êtes sûr de votre JSON envoyé, vous devez soigneusement suivre votre API:

  1. Installer le Microsoft.AspNet.WebApi.Tracingpackage
  2. Ajoutez config.EnableSystemDiagnosticsTracing();la méthode WebApiConfiginside class Register.

Regardez maintenant la sortie de débogage et vous trouverez probablement une ModelStateentrée de journal non valide .

Si ModelStaten'est pas valide, vous pouvez trouver la vraie cause dans son Errors:

Personne ne peut même deviner une telle exception:

Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Mohsen Afshin
la source
tu m'as sauvé la vie. Obtenu null en tant que modèle et après avoir installé le package, j'ai constaté que mon JSON n'est pas au format correct.
Khizar Iqbal
2

J'ai eu le même problème d'obtention de null en tant que paramètre, mais il était lié aux gros objets. Il s'est avéré que le problème était lié à la longueur maximale d'IIS. Il peut être configuré dans web.config.

  <system.web>
    <httpRuntime targetFramework="4.7" maxRequestLength="1073741824" />
  </system.web>

Je me demande pourquoi l'API Web a supprimé l'erreur et envoie des objets nuls à mes API. J'ai trouvé l'erreur en utilisant Microsoft.AspNet.WebApi.Tracing.

mohghaderi
la source
2

JSON.stringify (...) a résolu mes problèmes

ragnarswanson
la source
1

Je sais que ce n'est pas une réponse à cette question, mais je l'ai rencontrée lors de la recherche d'une solution à mon problème.

Dans mon cas, le type complexe n'était pas lié mais je ne faisais pas de POST, je faisais un GET avec des paramètres de chaîne de requête. La solution était d'ajouter [FromUri] à l'argument:

public class MyController : ApiController
{
    public IEnumerable<MyModel> Get([FromUri] MyComplexType input)
    {
        // input is not null as long as [FromUri] is present in the method arg
    }
}
danludwig
la source
En effet, le corps de la demande est ignoré (et provoque parfois une erreur) lors de l'utilisation de GET. La raison pour laquelle cela fonctionne maintenant est b / c, vous passez maintenant des paramètres sur la chaîne de requête, et votre corps est vide comme il se doit sur un GET
RyBolt
1

J'ai eu le même problème à Fiddler. J'avais déjà Content-Type: application/json; charset=utf-8ou Content-Type: application/jsondans l'en-tête de demande.

Mon corps de la demande a également été une chaîne de caractères, et Fiddler j'avais écrit: {'controller':'ctrl'}. Cela a fait que le paramètre de chaîne dans ma méthode POST soit null.

Correction : n'oubliez pas d'utiliser des guillemets, indiquant ainsi une chaîne. Autrement dit, je l'ai corrigé en écrivant "{'controller':'ctrl'}". (Remarque: lors de l'écriture de JSON, assurez-vous d'utiliser des apostrophes ou échappez aux guillemets comme ceci:) "{\"controller\":\"ctrl\"}".

gosr
la source
J'ai dû faire la même chose dans Postman. Mais je n'ai pas besoin de le faire lorsque j'appelle les services Spring. Cela ressemble à un problème du côté .Net.
Malcolm McRoberts
1

Le moyen le plus simple que j'ai trouvé pour gérer un objet JSON simple que je passe dans MVC 6 est d'obtenir le type du paramètre post comme NewtonSoft jObject:

public ActionResult Test2([FromBody] jObject str)
{
        return Json(new { message = "Test1 Returned: "+ str }); ;
}
Pini Cheyni
la source
Test ( [FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType) pourrait mieux fonctionner car la vérification bodyMediaType == "application.json"avant de lancer le corps sur JObject offre une opportunité pour les alternatives.
VladH
1

La meilleure solution pour moi est de passer au HTTP complet comme ci-dessous:

[Route("api/open")]
[HttpPost]
public async Task<string> open(HttpRequestMessage request)
{
    var json = await request.Content.ReadAsStringAsync();
    JavaScriptSerializer jss = new JavaScriptSerializer();            
    WS_OpenSession param = jss.Deserialize<WS_OpenSession>(json);
    return param.sessionid;
}

puis désérialisation de la chaîne à l'objet que vous attendez dans le corps du message. Pour moi, WS_OpenSession est une classe qui contenait sessionid, user et key.

Vous pouvez à partir de là utiliser l'objet param et accéder à ses propriétés.

Très très efficace.

J'ai dit provenir de cette URL:

http://bizcoder.com/posting-raw-json-to-web-api

Albertdadze
la source
1

Pour les types complexes, l'API Web essaie de lire la valeur dans le corps du message, à l'aide d'un formateur de type média.

Veuillez vérifier si vous avez obtenu un [Serializable]attribut décorant votre classe de modèle.

Supprimez l'attribut pour voir s'il fonctionne. Cela a fonctionné pour moi.

jaiveeru
la source
1

Je suis un peu en retard à la fête, mais toute personne tombant sur une valeur NULL a réussi lors de l'utilisation d'un contrôleur, ajoutez simplement "=" au début de votre demande POST.

Le contrôleur a également transmis une valeur NULL lorsque j'ai utilisé l' application / json Content-Type. Notez le type de contenu "application / x-www-form-urlencoded" ci-dessous. Le type de retour de l'API est cependant "application / json".

 public static string HttpPostRequest(string url, Dictionary<string, string> postParameters)
    {
        string postData = "=";

        foreach (string key in postParameters.Keys)
        {
            postData += HttpUtility.UrlEncode(key) + "="
                  + HttpUtility.UrlEncode(postParameters[key]) + ",";
        }

        HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
        myHttpWebRequest.Method = "POST";

        byte[] data = System.Text.Encoding.ASCII.GetBytes(postData);

        myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
        myHttpWebRequest.ContentLength = data.Length;

        Stream requestStream = myHttpWebRequest.GetRequestStream();
        requestStream.Write(data, 0, data.Length);
        requestStream.Close();

        HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

        Stream responseStream = myHttpWebResponse.GetResponseStream();

        StreamReader myStreamReader = new StreamReader(responseStream, System.Text.Encoding.Default);

        string pageContent = myStreamReader.ReadToEnd();

        myStreamReader.Close();
        responseStream.Close();

        myHttpWebResponse.Close();

        return pageContent;
    }
JTStuedle
la source
1

peu importe le type de valeur que vous souhaitez publier, placez-le simplement entre guillemets, pour l'obtenir sous forme de chaîne. Pas pour les types complexes.

javascript:

    var myData = null, url = 'api/' + 'Named/' + 'NamedMethod';

    myData = 7;

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = "some sentence";

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = { name: 'person name', age: 21 };

    $http.post(url, "'" + JSON.stringify(myData) + "'")
         .then(function (response) { console.log(response.data); });

    $http.post(url, "'" + angular.toJson(myData) + "'")
         .then(function (response) { console.log(response.data); });

c #:

    public class NamedController : ApiController
    {
        [HttpPost]
        public int NamedMethod([FromBody] string value)
        {
            return value == null ? 1 : 0;
        }
    }
Opochitsky Dimitry
la source
1

Si vous mettez l'annotation [FromBody] et que vous avez un objet Dto en tant que paramètre de votre méthode et que vous n'êtes toujours pas en mesure de passer les données, commencez à chercher dans les propriétés et les champs de votre DTO.

J'ai eu ce même problème, où mon DTO était devenu nul. J'ai trouvé que la raison était qu'une des propriétés pointait vers un objet qui ne peut pas être sérialisé :( ce qui empêche le formateur de média d'analyser les données. Ainsi, l'objet était toujours nul. J'espère qu'il aide les autres aussi

A AlTaiar
la source
1

Vérifiez vos types de données. Le classeur de modèle dotnet ne convertira pas un flottant en un entier (et je suppose que d'autres concepts connexes). Cela entraînera le rejet de l'ensemble du modèle.

Si vous avez json comme ceci:

{
    "shoeSize": 10.5
}

mais votre modèle c # ressemble à ceci:

class Shoe{
    public int shoeSize;
}

le classeur de modèle rejettera le modèle et vous obtiendrez nul.

TwitchBronBron
la source
1

Je suis assez tard pour cela, mais je rencontrais des problèmes similaires et après une journée passée à parcourir de nombreuses réponses ici et à obtenir des informations de base, j'ai trouvé la solution la plus simple / légère pour renvoyer un ou plusieurs paramètres à une action Web API 2. suit:

Cela suppose que vous savez comment configurer un contrôleur / une action d'API Web avec un routage correct, sinon reportez-vous à: https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with -aspnet-web-api / tutorial-your-first-web-api .

Tout d'abord l'action du contrôleur, cette solution nécessite également la bibliothèque Newtonsoft.Json.

[HttpPost]
public string PostProcessData([FromBody]string parameters) {
    if (!String.IsNullOrEmpty(parameters)) {
        JObject json = JObject.Parse(parameters);

        // Code logic below
        // Can access params via json["paramName"].ToString();
    }
    return "";
}

Côté client à l'aide de jQuery

var dataToSend = JSON.stringify({ param1: "value1", param2: "value2"...});
$.post('/Web_API_URI', { '': dataToSend }).done(function (data) {
     console.debug(data); // returned data from Web API
 });

Le problème clé que j'ai trouvé était de vous assurer de ne renvoyer qu'un seul paramètre global à l'API Web et de vous assurer qu'il n'a pas de nom juste la valeur { '': dataToSend } sinon votre valeur sera nulle côté serveur.

Avec cela, vous pouvez envoyer un ou plusieurs paramètres à l'API Web dans une structure JSON et vous n'avez pas besoin de déclarer des objets supplémentaires côté serveur pour gérer des données complexes. Le JObject vous permet également d'itérer dynamiquement tous les paramètres transmis afin de faciliter l'évolutivité si vos paramètres changent au fil du temps. Espérons que cela aide quelqu'un qui se débattait comme moi.

Nathan
la source
0

Le passage correct d'un seul paramètre dans le corps à WebAPI fonctionne ce code $.post(url, { '': productId }

Et l'attraper en action [HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)

La clé est d'utiliser le mot magique «valeur». Il peut également s'agir d'un entier ou d'un type primitif. Peu importe le type de contenu ou les corrections d'en-tête, Mess est que ce code ne fonctionne pas dans l'action post mvc.

Lapenkov Vladimir
la source