Azure APIM策略设置Body与返回响应遇500错误及数组校验问题
Azure APIM策略500错误排查及工单状态检查方案
一、set-body引发500错误的修复
你当前的set-body写法存在JSON格式隐患:当insured-id是字符串类型时,手动拼接的JSON会缺失引号,比如insured-id为"INS123"时,生成的请求体是{"insuredId": INS123},这不符合JSON语法,导致外部API解析失败,最终APIM返回500错误。
两种修复方式:
方式1:补全字符串引号
修改set-body为:<set-body>{"insuredId": "@(${(string)context.Variables["insured-id"]})"}</set-body>给插值结果套上双引号,确保字符串类型的
insuredId符合JSON格式。方式2:用JObject构建请求体(更推荐)
借助Newtonsoft.Json的JObject自动处理格式,彻底避免手动拼接的错误:<set-body>@(JObject.FromObject(new { insuredId = context.Variables["insured-id"] }).ToString())</set-body>这种方式会自动识别
insured-id的数据类型,生成合法的JSON结构。
二、检查工单数组中是否存在entityStatus=1的记录
原代码中直接通过["workRequests"]["entityStatus"]访问是错误的,因为workRequests是数组类型,不能直接用键值对的方式获取字段。需要遍历数组中的每个工单对象,判断是否存在符合条件的记录。
修改后的choose条件代码如下:
<choose> <when condition="@( ((IResponse)context.Variables["id"]).Body.As<JObject>(preserveContent: true)["workRequests"]? .As<JArray>() .Any(workReq => (int?)workReq["entityStatus"] == 1) )"> <return-response response-variable-name="id"> <set-status code="400" reason="VOID" /> <set-header name="Content-Type" exists-action="override"> <value>application/json</value> </set-header> <set-body>{"statusCode": 400, "message": "The insured cannot be voided as it is currently attached with one or more active workrequest"}</set-body> </return-response> </when> <otherwise /> </choose>
关键说明:
- 用
As<JArray>()将workRequests转换为数组类型,方便遍历 - 使用
Any()方法判断数组中是否存在任意一个工单的entityStatus等于1 - 添加
(int?)空值转换,避免部分工单缺失entityStatus字段时引发空引用异常
三、完整修正后的策略代码
<set-variable name="newRequest" value="@(context.Request.Body?.As<JObject>(preserveContent: true))" /> <set-variable name="insured-id" value="@(context.Request.MatchedParameters["id"].Last())" /> <send-request mode="new" timeout="20" response-variable-name="id" ignore-error="false"> <set-url>@($"https://api.dev.com/external/workRequest/get")</set-url> <set-method>POST</set-method> <set-header name="Content-Type" exists-action="override"> <value>application/json</value> </set-header> <set-header name="Authorization" exists-action="override"> <value>@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param"))</value> </set-header> <!-- 用JObject构建请求体,避免格式错误 --> <set-body>@(JObject.FromObject(new { insuredId = context.Variables["insured-id"] }).ToString())</set-body> </send-request> <choose> <when condition="@( ((IResponse)context.Variables["id"]).Body.As<JObject>(preserveContent: true)["workRequests"]? .As<JArray>() .Any(workReq => (int?)workReq["entityStatus"] == 1) )"> <return-response response-variable-name="id"> <set-status code="400" reason="VOID" /> <set-header name="Content-Type" exists-action="override"> <value>application/json</value> </set-header> <set-body>{"statusCode": 400, "message": "The insured cannot be voided as it is currently attached with one or more active workrequest"}</set-body> </return-response> </when> <otherwise /> </choose>
内容的提问来源于stack exchange,提问作者Shree
相关产品推荐
相关产品推荐

