Comment passer des données json POST à la méthode API Web en tant qu'objet?


Andrus:

L'application API Web ASP.NET MVC4 définit la méthode de publication pour enregistrer le client. Le client est passé au format json dans le corps de la requête POST. Le paramètre client dans la méthode de publication contient des valeurs nulles pour les propriétés.

Comment résoudre ce problème afin que les données publiées soient transmises en tant qu'objet client?

Si possible Content-Type: application / x-www-form-urlencoded doit être utilisé car je ne sais pas comment le changer dans la méthode javascript qui forme les messages.

Manette:

public class CustomersController : ApiController {

  public object Post([FromBody] Customer customer)
        {
            return Request.CreateResponse(HttpStatusCode.OK,
            new
            {
                customer = customer
            });
        }
    }
}

public class Customer
    {
        public string company_name { get; set; }
        public string contact_name { get; set; }
     }

Demande:

POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

{"contact_name":"sdfsd","company_name":"ssssd"}
Shyju:

MODIFIER : 31/10/2017

Le même code / approche fonctionnera également pour Asp.Net Core 2.0 . La principale différence est que, dans le noyau asp.net, les contrôleurs API Web et les contrôleurs Mvc sont fusionnés en un modèle de contrôleur unique. Ainsi , votre type de retour est peut - être IActionResultou l' un de ses mise en œuvre (Ex: OkObjectResult)


Utilisation

contentType:"application/json"

Vous devez utiliser une JSON.stringifyméthode pour le convertir en chaîne JSON lorsque vous l'envoyez,

Et le classeur de modèle liera les données json à votre objet de classe.

Le code ci-dessous fonctionnera correctement (testé)

$(function () {
    var customer = {contact_name :"Scott",company_name:"HP"};
    $.ajax({
        type: "POST",
        data :JSON.stringify(customer),
        url: "api/Customer",
        contentType: "application/json"
    });
});

Résultat

entrez la description de l'image ici

contentTypeproperty indique au serveur que nous envoyons les données au format JSON. Puisque nous avons envoyé une structure de données JSON, la liaison de modèle se produira correctement.

Si vous inspectez les en-têtes de la requête ajax, vous pouvez voir que la Content-Typevaleur est définie comme application/json.

Si vous ne spécifiez pas explicitement contentType, il utilisera le type de contenu par défaut qui est application/x-www-form-urlencoded;


Modifier en novembre 2015 pour résoudre d'autres problèmes éventuels soulevés dans les commentaires

Publier un objet complexe

Supposons que vous ayez une classe de modèle de vue complexe comme paramètre de méthode d'action de l'API Web comme celui-ci

public class CreateUserViewModel
{
   public int Id {set;get;}
   public string Name {set;get;}  
   public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
  public int Id {set;get;}
  public string Code {set;get;}
}

et le point de terminaison de votre API Web est comme

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewModel Save([FromBody] CreateUserViewModel m)
    {
        // I am just returning the posted model as it is. 
        // You may do other stuff and return different response.
        // Ex : missileService.LaunchMissile(m);
        return m;
    }
}

Au moment d'écrire ces lignes, ASP.NET MVC 6 est la dernière version stable et dans MVC6, les contrôleurs Web api et MVC héritent de la Microsoft.AspNet.Mvc.Controllerclasse de base.

Pour envoyer des données à la méthode du côté client, le code ci-dessous devrait fonctionner correctement

//Build an object which matches the structure of our view model class
var model = {
    Name: "Shyju",
    Id: 123,
    Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};

$.ajax({
    type: "POST",
    data: JSON.stringify(model),
    url: "../product/save",
    contentType: "application/json"
}).done(function(res) {       
    console.log('res', res);
    // Do something with the result :)
});

La liaison de modèle fonctionne pour certaines propriétés, mais pas toutes! Pourquoi ?

Si vous ne décorez pas le paramètre de méthode de l'API Web avec l' [FromBody]attribut

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}

Et envoyez le modèle (objet javascript brut, pas au format JSON) sans spécifier la valeur de la propriété contentType

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});

La liaison de modèle fonctionnera pour les propriétés plates sur le modèle, et non pour les propriétés où le type est complexe / d'un autre type. Dans notre cas, Idet les Namepropriétés seront correctement liées au paramètre m, mais la Tagspropriété sera une liste vide.

Le même problème se produira si vous utilisez la version courte, $.postqui utilisera le Content-Type par défaut lors de l'envoi de la demande.

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});

Articles connexes