Из моего клиента 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. Как получить тело запроса с соответствующими значениями?
Вы на правильном пути, но я могу внести некоторые уточнения.
Во-первых, код, который вы прокомментировали для чтения потока и преобразования его в строку, является правильным.
//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. Вы хотите сказать, что видите Content=null при открытии URL-адреса в браузере или после запуска JS-скрипта?
после того, как я разверну свое приложение-функцию на Azure и открою URL-адрес в браузере (ССЫЛКА на изображение: i.sstatic.net/CQbsTqrk.png)
Когда вы открываете приложение в браузере, вы не отправляете тело запроса, верно? Открытие сайта в браузере — это всего лишь пустой GET-запрос. Если вы хотите отправить запрос POST, используя тело запроса, вам следует использовать Postman или использовать свой скрипт в инструментах разработчика Chrome. Пожалуйста, обратитесь к моим двум нижним скриншотам. Вы увидите это на первом снимке экрана после открытия URL-адреса в браузере Content = пустая строка, но я использую ваш скрипт в Chrome Dev Tools, чтобы отправить запрос POST с данными и получить действительный ответ.
Нет, я отправил POST-запрос из веб-клиента, который открыт в другой вкладке, а затем открыл URL-адрес этой функции, чтобы проверить, получены ли совместные позы.
Я не уверен в этом случае. Моя интуиция подсказывает мне, что то, что вы пытаетесь сделать, потребует следующего: 1) При первом вызове POST сохраните тело запроса в статической переменной. 2) Получите значение этой статической переменной в последующих вызовах GET. Я чувствую, что это не то, что вы пытаетесь сделать, поскольку вы представили «serviceHubContext.Clients.All.SendAsync», который, похоже, взят из SignalR и с которым я не знаком. Я бы рекомендовал задать новый вопрос и описать этот новый вариант использования.
спасибо за рекомендацию. Я использую SignalR, но это не имеет к этому никакого отношения, поскольку все, что мне нужно, — это получить тело URL-адреса, отправленное с помощью метода POST в приложение-функцию Azure. Я не понимаю. Если мой подход действителен, почему я не получаю данные?
Я чувствую, что это работает, но вы неправильно понимаете, что вы должны видеть в пользовательском интерфейсе. Можете ли вы подтвердить, что инструменты Chrome Dev и действия Postman, которыми я поделился, работают у вас? Если при выполнении этих шагов вы получаете тело запроса, значит, функция получает данные.
Да, я могу подтвердить, что использование POSTMAN API мне подходит, и я могу получать данные в теле ответа. Однако цель состоит в том, чтобы увидеть данные на веб-странице, когда я открываю URL-адрес. Как мне этого добиться?
В этом случае мы можем использовать статическую переменную для хранения содержимого тела запроса. Я поделился новым кодом функции, который использует этот метод.
Нет проблем, рад это слышать
спасибо за Ваш ответ. После пересмотра моей функции в соответствии с вашими предложениями я получаю Content=null. Новый скрипт можно найти выше. Не могли бы вы предложить что-нибудь?