Тело правильное, так почему значение post равно нулю - PullRequest
0 голосов
/ 22 марта 2019

Как и многие другие (например, 36 ответов здесь ), когда я публикую строку в ASP.Net Core, значение всегда равно нулю.Я попытался [FromBody], но в результате мои звонки получили ошибку 400.В конце концов я нашел это «решение», которое работает:

[Route("api/[controller]")]
[ApiController]
public class ScoresController : ControllerBase
{
    [HttpPost]
    public void Post(string value)
    {
        # 'value' is null, so ...
        Request.EnableRewind();
        var body = "";
        using (var reader = new StreamReader(Request.Body))
        {
            Request.Body.Seek(0, SeekOrigin.Begin);
            body = reader.ReadToEnd();
        }
        value = body;
        # Now 'value' is correct, use it ...
    }
}

Вот пример значения, которое я отправляю от клиента (Python, используя «запросы»):

'{"Имя пользователя": "TestUserNumber5", "Email": "testuser5@nowhere.com", "PasswordHash": 5}'

и как только я получил его из тела в ASP.Net Core выглядит следующим образом:

"{\" Имя пользователя \ ": \" TestUserNumber5 \ ", \" Email \ ": \" testuser5@nowhere.com \ ", \" PasswordHash \ "": 5}"

Я не устанавливаю явно тип содержимого, вот код Python, который я использую для публикации:

def add_score(score):
    score_json = json.dumps(score)
    response = requests.post(url+"scores/", data=score_json, verify=False)
    return response.ok

Чтение тела во второй раз кажется оченьHacky.Зачем мне это нужно?

1 Ответ

0 голосов
/ 22 марта 2019

Есть некоторая критическая информация, которая была исключена: а именно, является ли это контроллером в стиле API, используете ли вы атрибут [ApiController], или как вы делаете пост (x-www-form-urlencoded, application/json, text/plain и т. д. Однако я сделаю некоторые предположения на основе поведения, которое вы испытываете.

Если бы мне пришлось угадывать, я бы сказал, что это контроллер в стиле API, и к вам применен атрибут [ApiController]. По умолчанию это переключит привязку на [FromBody], но только для типов классов, а не для примитивных типов, таких как string. Таким образом, по умолчанию ваш строковый параметр в основном игнорируется. Когда вы явно применяете атрибут [FromBody] к параметру, вы затем принудительно привязываете к нему тело запроса, и то, что вы отправляете, не может быть (отсюда 400 неверных запросов).

Так что это подводит нас к тому, что вы публикуете. Скорее всего, вы отправляете application/json в качестве типа контента, но ваше тело запроса просто my string value. Это недопустимый JSON, и вы получите 400. Если вы хотите отправить просто строку в виде JSON, тогда это должна быть строка JSON , что в основном означает, что ее нужно заключить в кавычки: "my string value". Вам по-прежнему понадобится атрибут [FromBody], явно примененный к параметру, но если вы добавите кавычки, он пройдет.

UPDATE

И именно поэтому код так важен для вопроса. Похоже, что вы отправляете его с клиента в виде строки, а затем привязываете ее к строке в приложении ASP.NET Core. Однако фактическими данными являются JSON.

Проблема в том, что для примитивного типа, такого как string, привязка по умолчанию будет FromForm. Однако вы не отправляете запрос x-www-form-urlencoded. Добавление [FromBody] тоже не сработало, потому что хотя выглядит как JSON, оно не отправляется с типом содержимого JSON. На самом деле ваш тип контента, скорее всего, text/plain, а в ASP.NET Core по умолчанию не применяется форматировщик ввода text/plain. Вы можете изменить это, но это действительно не идеально.

Проще говоря, у вас есть объект, который вы хотите передать через HTTP в API. Это означает, что вы должны использовать объектно-ориентированный формат, такой как JSON или XML. На стороне Python отправляйте ваш запрос как фактический JSON, а не как строку, содержащую сериализованный объект JSON. На стороне ASP.NET Core создайте класс, который имеет свойства для членов этого объекта JSON, и используйте его в качестве параметра. Тогда у вас не будет проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...