Как получить строку JSON из тела запроса метода POST в функциях Azure?

Из моего клиента JavaScript я отправляю данные JSON с помощью метода POST.

fetch("https://%$%$%%$.azurewebsites.net/api/JointPose?", {
                    method: "POST",
                    body: JSON.stringify({
                        JointPose1: `${Joint1Pose}`,
                        JointPose2: `${Joint2Pose}`,
                        JointPose3: `${Joint3Pose}`,
                        JointPose4: `${Joint4Pose}`,
                        JointPose5: `${Joint5Pose}`,
                        JointPose6: `${Joint6Pose}`,
                        JointPose7: `${Joint7Pose}`
                    }),
                    headers: {
                        "Content-Type": "application/json; charset=UTF-8",
                    }
                })
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Network response was not ok ' + response.statusText);
                        }
                        return response.json();
                    })
                    .then(data => {
                        console.info('Success:', data);
                    })
                    .catch(error => {
                        console.error('Error:', error);
                    });

Я пытаюсь получить тело запроса с помощью HTTPtrigger в приложении «Функции Azure».

public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "JointPose")] HttpRequest req)
        {
            MemoryStream ms = new MemoryStream();
            await req.Body.CopyToAsync(ms);
            string jointPoseData = ms.ToString();

            //using StreamReader reader = new(req.Body);
            //string bodyStr = await reader.ReadToEndAsync();
            //var jointPoseData = JsonConvert.DeserializeObject<JointPoseData>(bodyStr);

            return new OkObjectResult( new { Content = new StringContent(JsonConvert.SerializeObject(jointPoseData), Encoding.UTF8, "application/json") });
        }

public class JointPoseData
    {
        public string JointPose1 { get; set; }
        public string JointPose2 { get; set; }
        public string JointPose3 { get; set; }
        public string JointPose4 { get; set; }
        public string JointPose5 { get; set; }
        public string JointPose6 { get; set; }
        public string JointPose7 { get; set; }
    }

Ответ, который я получаю после открытия URL-адреса:

При открытии URL-ссылки в браузере

Ожидаемый результат:

JointPose1: 0,31, JointPose2: 0,32,.......

Пересмотренный скрипт для функции

[FunctionName("GetJointData")]
        public static async Task<IActionResult> GetJointData(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "JointPose")] HttpRequest req)
        {
            using StreamReader reader = new(req.Body);
            string bodyStr = await reader.ReadToEndAsync();
            await serviceHubContext.Clients.All.SendAsync("jointPose", JsonConvert.SerializeObject(bodyStr));
            return new OkObjectResult(new
            {
                Content = JsonConvert.SerializeObject(bodyStr)
            });
        }

Я получаю этот ответ в консоли моего браузера

Контент нулевой

Я думаю, что JointPoseData имеет значение null. Как получить тело запроса с соответствующими значениями?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы на правильном пути, но я могу внести некоторые уточнения.

Во-первых, код, который вы прокомментировали для чтения потока и преобразования его в строку, является правильным.

//using StreamReader reader = new(req.Body);
//string bodyStr = await reader.ReadToEndAsync();
//var jointPoseData = JsonConvert.DeserializeObject<JointPoseData>(bodyStr);

Код, который вы раскомментировали для чтения потока, не будет работать из-за ms.ToString();. В C# каждый класс имеет метод .ToString(), поскольку каждый класс является производным от Object, который содержит этот метод. Классы могут переопределять этот метод, но по умолчанию он просто выводит имя типа. Поэтому в вашем коде переменная «ms» будет просто содержать значение «System.IO.MemoryStream».

Переходя к возврату функции, нам нужно использовать OkObjectResult, который вы правильно использовали, и мы можем просто передать строку в конструктор. Если вы хотите, чтобы строка находилась в свойстве «Содержимое», мы можем передать анонимный объект со свойством «Содержимое» и передать строку в качестве значения. StringContent здесь неприменим, поскольку это класс, используемый в HttpClients. Следует также отметить, что если все, что вы хотите сделать, это вывести тело запроса, нет необходимости десериализовать, а затем сериализовать обратно.

В результате получается следующий код:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;

namespace Payments.PaymentInstrumentRouter
{
    public class TestingFunction
    { 
        [Function("TestingFunction")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
        {
            using StreamReader reader = new(req.Body);
            string bodyStr = await reader.ReadToEndAsync();

            return new OkObjectResult(new
            {
                Content = bodyStr
            });
        }
    }
    public class JointPoseData
    {
        public string JointPose1 { get; set; }
        public string JointPose2 { get; set; }
        public string JointPose3 { get; set; }
        public string JointPose4 { get; set; }
        public string JointPose5 { get; set; }
        public string JointPose6 { get; set; }
        public string JointPose7 { get; set; }
    }
}

Теперь переходим к вызову функции. Если вы вызываете функцию, используя сценарий, которым вы поделились, с помощью инструментов Chrome Dev или в почтальоне, вы сможете увидеть выходное содержимое вместе с телом запроса:

Надеюсь, это ответило на ваш вопрос. Поделитесь, если есть сомнения.

Обновлено:

В комментариях был задан вопрос "Как можно просмотреть данные, отправленные в теле POST-запроса, в другом запросе?"

Мы можем использовать статическую переменную для хранения значения тела запроса. Статические переменные связаны с самим классом, а не с экземплярами класса, и, следовательно, их можно использовать для сохранения данных в различных запросах. Мы также можем добавить условие, чтобы установить значение этой переменной, только если мы выполняем запрос POST.

public class TestingFunction
{
    private static string RequestBody { get; set; }

    [Function("TestingFunction")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
    {
        using StreamReader reader = new(req.Body);
        string bodyStr = await reader.ReadToEndAsync();

        if (req.Method == "POST")
        {
            RequestBody = bodyStr;
        }

        return new OkObjectResult(new
        {
            Content = RequestBody
        });
    }
}

спасибо за Ваш ответ. После пересмотра моей функции в соответствии с вашими предложениями я получаю Content=null. Новый скрипт можно найти выше. Не могли бы вы предложить что-нибудь?

Astroboy 26.07.2024 12:34

Сценарий правильный, но у меня вопрос, где вы видите Content=null. Вы хотите сказать, что видите Content=null при открытии URL-адреса в браузере или после запуска JS-скрипта?

ifg43 26.07.2024 15:40

после того, как я разверну свое приложение-функцию на Azure и открою URL-адрес в браузере (ССЫЛКА на изображение: i.sstatic.net/CQbsTqrk.png)

Astroboy 26.07.2024 16:53

Когда вы открываете приложение в браузере, вы не отправляете тело запроса, верно? Открытие сайта в браузере — это всего лишь пустой GET-запрос. Если вы хотите отправить запрос POST, используя тело запроса, вам следует использовать Postman или использовать свой скрипт в инструментах разработчика Chrome. Пожалуйста, обратитесь к моим двум нижним скриншотам. Вы увидите это на первом снимке экрана после открытия URL-адреса в браузере Content = пустая строка, но я использую ваш скрипт в Chrome Dev Tools, чтобы отправить запрос POST с данными и получить действительный ответ.

ifg43 26.07.2024 17:47

Нет, я отправил POST-запрос из веб-клиента, который открыт в другой вкладке, а затем открыл URL-адрес этой функции, чтобы проверить, получены ли совместные позы.

Astroboy 26.07.2024 17:56

Я не уверен в этом случае. Моя интуиция подсказывает мне, что то, что вы пытаетесь сделать, потребует следующего: 1) При первом вызове POST сохраните тело запроса в статической переменной. 2) Получите значение этой статической переменной в последующих вызовах GET. Я чувствую, что это не то, что вы пытаетесь сделать, поскольку вы представили «serviceHubContext.Clients.All.SendAsync», который, похоже, взят из SignalR и с которым я не знаком. Я бы рекомендовал задать новый вопрос и описать этот новый вариант использования.

ifg43 27.07.2024 03:04

спасибо за рекомендацию. Я использую SignalR, но это не имеет к этому никакого отношения, поскольку все, что мне нужно, — это получить тело URL-адреса, отправленное с помощью метода POST в приложение-функцию Azure. Я не понимаю. Если мой подход действителен, почему я не получаю данные?

Astroboy 29.07.2024 12:09

Я чувствую, что это работает, но вы неправильно понимаете, что вы должны видеть в пользовательском интерфейсе. Можете ли вы подтвердить, что инструменты Chrome Dev и действия Postman, которыми я поделился, работают у вас? Если при выполнении этих шагов вы получаете тело запроса, значит, функция получает данные.

ifg43 29.07.2024 16:52

Да, я могу подтвердить, что использование POSTMAN API мне подходит, и я могу получать данные в теле ответа. Однако цель состоит в том, чтобы увидеть данные на веб-странице, когда я открываю URL-адрес. Как мне этого добиться?

Astroboy 29.07.2024 18:24

В этом случае мы можем использовать статическую переменную для хранения содержимого тела запроса. Я поделился новым кодом функции, который использует этот метод.

ifg43 29.07.2024 22:43

Нет проблем, рад это слышать

ifg43 30.07.2024 16:26

Другие вопросы по теме

Как полностью остановить локальный запуск функции Azure? Функция Azure [Python V2] продолжает предыдущее выполнение при перезапуске отладчика [VS Code]?
Получение исключения «Невозможно динамически создать экземпляр типа Microsoft.Azure.Functions.Worker.Http.HttpRequestData». в функции Azure
Функции Azure не принимают значение в кодировке URL-адреса в качестве параметра запроса?
Как запустить функцию HTTP-триггера с помощью трепетания кнопки?
Разработка и развертывание функций Azure локально с использованием кода VS
Не удалось найти тип или имя пространства имен «Id» (вам не хватает директивы using или ссылки на сборку?) Проблема CosmosDBOutput
Функции Azure (срабатывающие по протоколу Http) начали случайным образом вызывать исключение TaskCancelled Exception
Как исправить ImportError с помощью EventGridPublisherClient в функции Azure HTTPTrigger?
Как отредактировать файл httptrigger function.json для проекта, загруженного VSCode
Как функция azure HttpTrigger редактирует имя параметра кода?

Похожие вопросы

Получение «System.IO.FileNotFoundException: не удалось загрузить файл или сборку Azure.Core, версия = 1.38.0.0» в приложении-функции Azure
Конвейер ci, создающий артефакт для приложения-функции, не содержит функций
Функция Azure с проблемой сети речи Azure AI (WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED)
Ошибка конвейера приложения-функции Azure для Key Vault: имя параметра не может быть пустым
Как создать функцию Azure, которая развертывает мой сценарий бицепса из учетной записи хранения Azure
Попытка подключиться к базе данных SQL — поставщик: поставщик TCP, ошибка: 26 — ошибка при обнаружении указанного сервера/экземпляра
Монитор хранилища функциональных BLOB-объектов Azure
Обработка WorkerErrorEvent для среды выполнения: dotnet-isolated, workerId: dotnet-isolated. Ошибка: System.TimeoutException: время ожидания операции истекло
Скрипты для уведомления об очереди недоставленных писем
Как скачать файл в учетную запись хранения Azure из приложения-функции