MVC-контроллер: получить объект JSON из тела HTTP? - программирование
Подтвердить что ты не робот

MVC-контроллер: получить объект JSON из тела HTTP?

У нас есть приложение MVC (MVC4), которое иногда может отправлять события JSON, отправленные сторонней организацией по нашему конкретному URL (" http://server.com/events/ "). Событие JSON находится в теле HTTP POST, а тело - строго JSON (Content-Type: application/json - не пост-форма с JSON в некотором строковом поле).

Как я могу получить тело JSON внутри тела контроллера? Я попробовал следующее, но ничего не получил

[Редактировать]: Когда я сказал, что ничего не получил, я имел в виду, что jsonBody всегда равен null, независимо от того, определяю ли я его как Object или string.

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

Обратите внимание, что я знаю, если я дам объявление метода со строго типизированным входным параметром, MVC выполняет весь анализ и фильтрацию, т.е.

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

Однако JSON, который мы получаем, очень разнообразен, поэтому мы не хотим определять (и поддерживать) сотни различных классов для каждого варианта JSON.

Я проверяю это с помощью следующей команды curl (с одним вариантом JSON здесь)

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 }}}
4b9b3361

Ответ 1

Кажется, что если

  • Content-Type: application/json и
  • если тело POST не привязано к классу входных объектов контроллера

Тогда MVC на самом деле не связывает тело POST с каким-либо конкретным классом. Также вы не можете просто получить тело POST в качестве параметра ActionResult (предлагается в другом ответе). Справедливо. Вам нужно извлечь его из потока запросов самостоятельно и обработать.

[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

}

Обновить:

для ядра Asp.Net вы должны добавить [FromBody] рядом с именем вашего параметра в действии контроллера для сложных типов данных JSON:

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

Также, если вы хотите получить доступ к телу запроса в виде строки, чтобы проанализировать его самостоятельно, вы должны использовать Request.Body вместо Request.InputStream:

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

Ответ 2

используйте Request.Form, чтобы получить данные

Контроллер:

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

Я пишу это, чтобы попробовать

Вид:

<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>

и писать Request.Form[0] или Request.Params[0] в контроллере могут получить данные.

Я не пишу <form> tag.

Ответ 3

Как только вы определите класс (MyDTOClass), указывающий, что вы ожидаете получить, он должен быть таким же простым, как...

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

спасибо to Julias:

Разбор Json.NET Web Api

Убедитесь, что ваш запрос отправлен с заголовком http:

Content-Type: application/json

Ответ 4

вы можете получить строку json в качестве параметра вашего ActionResult, а затем сериализуйте его с помощью JSON.Net

ЗДЕСЬ показан пример


чтобы получить его в сериализованной форме в качестве параметра действия контроллера, вы должны либо написать настраиваемое связующее устройство, либо фильтр действий (OnActionExecuting), чтобы строка json была сериализована в модель по вашему вкусу и доступна внутри корпуса контроллера для использования.


ЗДЕСЬ - это реализация с использованием динамического объекта

Ответ 5

Я пытался заставить мой контроллер ASP.NET MVC проанализировать некоторую модель, которую я представил ему с помощью Postman.

Мне нужно было следующее, чтобы заставить его работать:

  • действие контроллера

    [HttpPost]
    [PermitAllUsers]
    [Route("Models")]
    public JsonResult InsertOrUpdateModels(Model entities)
    {
        // ...
        return Json(response, JsonRequestBehavior.AllowGet);
    }
    
  • класс моделей

    public class Model
    {
        public string Test { get; set; }
        // ...
    }
    
  • заголовки для запроса почтальона, в частности, Content-Type

    postman headers

  • JSON в теле запроса

    enter image description here