Подтвердить что ты не робот

ASP.NET Core MVC: как получить необработанный JSON привязан к строке без типа?

Как и этот старый вопрос о предыдущих версиях ASP.NET, я хочу, чтобы тело запроса HTTP POST было привязано к строке. Кажется, что метод связывается, но value имеет значение null, когда ASP.NET вызывает мой метод контроллера:

namespace Demo.Controllers
{

    [Route("[controller]")]
    public class WebApiDemoController : Controller
    {
    ...

    // POST api/values
    [HttpPost]
    public System.Net.Http.HttpResponseMessage Post([FromBody]string value)
    {
       // expected: value = json string, actual: json = null.
    }

Должен ли я все-таки ухватиться за тело из потока? Или это просто работает? При тестировании вышеописанного метода я использовал следующие заголовки http:

Accept: Application/json
Content-Type: Application/json;charset=UTF-8

Я передаю следующее в теле: { "a": 1 }

Я НЕ хочу привязываться к строковой переменной с именем a. Я хочу связать любой JSON, который я получаю, а затем я хочу использовать контент JSON, любой произвольный контент, из моего метода.

Если я понял документацию, атрибут [FromBody] должен был сделать то, что я хотел, но я предполагаю, что основной механизм привязки MVC для ASP.NET не привяжет json к "строковому значению", но, возможно, Я мог бы сделать что-то еще, что дает мне эквивалентный уровень гибкости.

Подобный вопрос здесь дает мне идею, может быть, я должен был написать [FromBody] dynamic data вместо использования [FromBody] string value.

Обновление. Об этом следует подумать, прежде чем делать это, потому что если вы хотите, чтобы ядро ​​core.net обрабатывало JSON и XML-кодировку, вы просто убили эту возможность. Некоторые типы серверов REST могут и часто имеют требования к поддержке типов контента XML и JSON, по крайней мере, тех, с которыми я столкнулся, которые имеют документы стандартов.

4b9b3361

Ответ 1

Следующее работает в .net core 1.x, но не в .net core 2.x.

Как я уже [FromBody]dynamic data, решение состоит в том, чтобы использовать [FromBody]dynamic data качестве моего списка параметров, используя вместо string dynamic, и я получу JObject.

Предостережение. Если ваша архитектура требует, чтобы один и тот же сервер WebApi одинаково свободно создавал XML и JSON, в зависимости от записей заголовка типа контента, такая стратегия прямого использования JSON может иметь неприятные последствия. (Поддержка XML и JSON в одной и той же службе возможна при достаточной работе, но затем вы берете материал, который был далее вверх по конвейеру ресурсов MVC, и перемещаете его вниз в методы вашего контроллера, что, оказывается, противоречит духу MVC где модели приходят к вам как POCOs уже разобраны.)

Как только вы преобразуете в строку внутри метода, конвертирование входящего JObject (Newtonsoft.JSON в типе данных памяти для JSON) в строку.

Нашел другой ответ здесь.

Пример кода, благодаря Jeson Martajaya:

С динамическим:

[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]dynamic value)
{
   //...
}

Пример кода с JObject:

[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]Newtonsoft.Json.Linq.JObject value)
{
   //...
}

Ответ 2

Самый чистый вариант, который я нашел, добавляет ваш собственный простой InputFormatter:

public class RawJsonBodyInputFormatter : InputFormatter
{
    public RawJsonBodyInputFormatter()
    {
        this.SupportedMediaTypes.Add("application/json");
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        var request = context.HttpContext.Request;
        using (var reader = new StreamReader(request.Body))
        {
            var content = await reader.ReadToEndAsync();
            return await InputFormatterResult.SuccessAsync(content);
        }
    }

    protected override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }
}

И в вашем Startup.cs внутри ConfigureServices:

services
    .AddMvc(options =>
    {
        options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
    });

Это позволит вам получить необработанную полезную нагрузку JSON в ваших контроллерах:

[HttpPost]
public IActionResult Post([FromBody]string value)
{
    // value will be the request json payload
}

Ответ 3

В качестве альтернативы вы также можете просто принять JObject, и вы сможете использовать Linq для Json даже прямо ToString(), если вам действительно нужна строка.

Ответ 4

Я вижу, что Сэм уже проголосовал за то, что он говорил почти то же самое, но при тестировании с помощью Postman я обнаружил, что если я установлю тело запроса на простое строковое выражение с двойными кавычками, то ASP свяжет его с по умолчанию '[ FromBody] string value.

"just send your string like this without any curly braces"

Не уверен, что приложение /json должно принимать данные в этом формате. Хотелось бы надеяться, разместив это, кто-то знающий будет трудиться и указать, действительно ли это или нет.

Ответ 5

Следующие два метода работают в ASP.NET core 2 для чтения необработанной строки json.

1) Этот имеет лучшую производительность.

    [HttpPost]
    public async Task<ActionResult<int>> Process()
    {
        string jsonString;
        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
        {
            jsonString = await reader.ReadToEndAsync();
        }

2)

    [HttpPost]
    public async Task<ActionResult<int>> Process([FromBody]JToken jsonbody)
    {
        var jsonString = jsonBody.ToString();

Ответ 6

Вам нужен тип для привязки данных. Пример:

public class Person
{
   public string Name {get; set;}
}

для данных { "Name" : "James"}

Ответ 7

Если вы хотите получить строку, вам нужно передать ее как строку. Ваш JSON должен быть заключен в кавычки:

'{ "a": 1 }'