web-dev-qa-db-fra.com

Contrôleur MVC: obtenir un objet JSON à partir du corps HTTP?

Nous avons une application MVC (MVC4) qui peut parfois recevoir un événement JSON POST d'une tierce partie sur notre URL spécifique (" http://server.com/events/ "). L'événement JSON est dans le corps du HTTP POST et le corps est strictement JSON (Content-Type: application/json - pas un formulaire-post avec JSON dans un champ de chaîne).

Comment puis-je recevoir le corps JSON à l'intérieur du corps du contrôleur? J'ai essayé ce qui suit mais je n'ai rien eu

[Edit]: Quand je dis rien obtenu je voulais dire que jsonBody est toujours nul, que je le définisse comme Object ou string

[HttpPost]
// this maps to http://server.com/events/
// why is jsonBody always null ?!
public ActionResult Index(int? id, string jsonBody)
{
    // Do stuff here
}

Notez que si je donne à déclarer la méthode avec un paramètre d’entrée fortement typé, MVC effectue l’ensemble de l’analyse et du filtrage, c.-à-d.

// this tested to work, jsonBody has valid json data 
// that I can deserialize using JSON.net
public ActionResult Index(int? id, ClassType847 jsonBody) { ... }

Cependant, le JSON que nous obtenons est très varié, nous ne souhaitons donc pas définir (ni maintenir) des centaines de classes différentes pour chaque variante JSON.

Je teste cela avec la commande curl suivante (avec une variante du JSON ici)

curl -i -H "Host: localhost" -H "Content-Type: application/json" -X POST http://localhost/events/ -d '{ "created": 1326853478, "data": { "object": { "num_of_errors": 123, "fail_count": 3 }}}
57
DeepSpace101

Il semble que si 

  • Content-Type: application/json et
  • si le corps POST n'est pas étroitement lié à la classe d'objet d'entrée du contrôleur

Ensuite, MVC ne lie pas vraiment le corps POST à une classe particulière. Vous ne pouvez pas non plus simplement extraire le corps POST en tant que paramètre de ActionResult (suggéré dans une autre réponse). C'est suffisant. Vous devez le récupérer vous-même à partir du flux de demandes et le traiter. 

[HttpPost]
public ActionResult Index(int? id)
{
    Stream req = Request.InputStream;
    req.Seek(0, System.IO.SeekOrigin.Begin);
    string json = new StreamReader(req).ReadToEnd();

    InputClass input = null;
    try
    {
        // assuming JSON.net/Newtonsoft library from http://json.codeplex.com/
        input = JsonConvert.DeserializeObject<InputClass>(json)
    }

    catch (Exception ex)
    {
        // Try and handle malformed POST body
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    //do stuff

}

Mettre à jour:

pour Asp.Net Core, vous devez ajouter [FromBody] attrib à côté de votre nom de paramètre dans l'action de votre contrôleur pour les types de données JSON complexes:

[HttpPost]
public ActionResult JsonAction([FromBody]Customer c)

De plus, si vous souhaitez accéder au corps de la requête sous forme de chaîne pour l'analyser vous-même, vous devez utiliser Request.Body au lieu de Request.InputStream:

Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
116
DeepSpace101

utiliser Request.Form pour obtenir les données

Manette:

    [HttpPost]
    public ActionResult Index(int? id)
    {
        string jsonData= Request.Form[0]; // The data from the POST
    }

J'écris ceci pour essayer 

Vue:

<input type="button" value="post" id="btnPost" />

<script type="text/javascript">
    $(function () {
        var test = {
            number: 456,
            name: "Ryu"
        }
        $("#btnPost").click(function () {
            $.post('@Url.Action("Index", "Home")', JSON.stringify(test));
        });
    });
</script>

et écrire Request.Form[0] ou Request.Params[0] dans le contrôleur peut obtenir les données.

Je n'écris pas <form> tag en vue.

6
ChunHao Tang

Une fois que vous avez défini une classe (MyDTOClass) indiquant ce que vous attendez, elle devrait être aussi simple que ...

public ActionResult Post([FromBody]MyDTOClass inputData){
 ... do something with input data ...
}

Thx à Julias:

Analyse de Json .Net Web Api

Assurez-vous que votre demande est envoyée avec l'en-tête http:

Type de contenu: application/json

1
andrew pate

J'ai essayé d'obtenir que mon contrôleur ASP.NET MVC analyse un modèle que je lui ai soumis à l'aide de Postman .

J'avais besoin de ce qui suit pour le faire fonctionner:

  • action du contrôleur

    [HttpPost]
    [PermitAllUsers]
    [Route("Models")]
    public JsonResult InsertOrUpdateModels(Model entities)
    {
        // ...
        return Json(response, JsonRequestBehavior.AllowGet);
    }
    
  • une classe de modèles

    public class Model
    {
        public string Test { get; set; }
        // ...
    }
    
  • en-têtes pour la demande de Postman, plus précisément, Content-Type

    postman headers

  • json dans le corps de la demande

    enter image description here

1
Eric

vous pouvez obtenir la chaîne json en tant que paramètre de votre ActionResult puis la sérialiser à l'aide de JSON.Net

ICI un exemple est montré


pour le recevoir sous forme sérialisée en tant que paramètre de l'action du contrôleur, vous devez écrire un classeur de modèle personnalisé ou un filtre Action (OnActionExecuting) afin que la chaîne json soit sérialisée dans le modèle de votre choix et disponible dans le contrôleur corps pour l'utilisation.


HERE est une implémentation utilisant l'objet dynamique 

0
user1770234