如何在Azure Functions中获取POST请求体的JSON字符串?
问题描述
我用JavaScript客户端通过POST发送JSON数据,代码如下:
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.log('Success:', data); }) .catch(error => { console.error('Error:', error); });
尝试在Azure Functions的HTTP Trigger中获取请求体,初始代码如下:
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后响应不符合预期,我期望输出类似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) }); }
但浏览器控制台显示Content为null,请求体数据无法正确获取,请问该怎么解决?
解决方案
1. 最优实现:直接绑定模型读取请求体
Azure Functions支持直接将请求体反序列化为指定模型,无需手动处理流,这是最可靠的方式:
[FunctionName("GetJointData")] public static async Task<IActionResult> GetJointData( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "JointPose")] HttpRequest req, ILogger log) { // 直接将请求体反序列化为JointPoseData模型 var jointPoseData = await req.ReadFromJsonAsync<JointPoseData>(); if (jointPoseData == null) { return new BadRequestObjectResult("无效的请求体格式"); } // 发送数据到SignalR(保持你的业务逻辑) await serviceHubContext.Clients.All.SendAsync("jointPose", jointPoseData); // 返回符合预期格式的响应 return new OkObjectResult(new { JointPose1 = jointPoseData.JointPose1, JointPose2 = jointPoseData.JointPose2, JointPose3 = jointPoseData.JointPose3, JointPose4 = jointPoseData.JointPose4, JointPose5 = jointPoseData.JointPose5, JointPose6 = jointPoseData.JointPose6, JointPose7 = jointPoseData.JointPose7 }); } 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; } }
2. 原代码失败原因分析
- 初始代码中
ms.ToString()不会读取内存流的内容,而是返回System.IO.MemoryStream字符串,完全不是请求体数据。 - 修改后的代码若返回null,大概率是请求体流读取后未重置位置,或客户端发送的JSON格式有误。手动读取流时必须重置位置:
using StreamReader reader = new(req.Body); string bodyStr = await reader.ReadToEndAsync(); req.Body.Position = 0; // 重置流位置,避免后续读取失败 var jointPoseData = JsonConvert.DeserializeObject<JointPoseData>(bodyStr);
3. 额外检查项
- 确认客户端的
Joint1Pose等变量有实际值,可在fetch前打印JSON.stringify(...)的结果验证。 - 确保HTTP Trigger只保留
post方法(你不需要处理get请求,避免误触发)。
内容的提问来源于stack exchange,提问作者Astroboy
相关产品推荐
相关产品推荐

