D365 X++服务端调用外部REST API及报错代码修复
Dynamics 365 F&O X++调用外部API修复方案(解决Bad Request错误)
原代码问题分析
导致Bad Request错误的核心问题如下:
- Content-Type配置错误:发送JSON格式请求体却设置为
text/html,服务端无法解析请求内容 - 请求头部格式无效:
"Pass Owner Id"和"GSTIN"仅声明了头部键名,未设置对应值,且头部名称包含空格不符合HTTP规范 - Response实例初始化错误:直接
new System.Net.HttpWebResponse()属于无效操作,响应实例应由request.GetResponse()返回 - 资源释放不严谨:异常场景下流和响应对象未被正确关闭,易引发资源泄漏
- 存在大量未使用的冗余变量,增加代码复杂度
修复后的HttpWebRequest版本代码
public static void main(Args _args) { str destinationUrl = "https://xyz.com/api/your-endpoint"; // 替换为实际接口地址 str requestJson = '{"param1":"value1","param2":"value2"}'; // 替换为实际JSON请求体 str responseJson; System.Net.HttpWebRequest request; System.Net.HttpWebResponse response; System.Byte[] bytes; System.Text.Encoding utf8; System.IO.Stream requestStream, responseStream; System.IO.StreamReader streamReader; System.Exception ex; System.Net.WebHeaderCollection httpHeader; try { new InteropPermission(InteropKind::ClrInterop).assert(); httpHeader = new System.Net.WebHeaderCollection(); request = System.Net.WebRequest::Create(destinationUrl); utf8 = System.Text.Encoding::get_UTF8(); bytes = utf8.GetBytes(requestJson); // 设置请求方法 request.set_Method("POST"); // 修正Content-Type为JSON格式 httpHeader.Add("Content-Type: application/json; charset=utf-8"); // 规范自定义头部格式并补充值(替换为实际业务值) httpHeader.Add("Pass-Owner-Id: your-owner-id"); httpHeader.Add("GSTIN: your-gstin-value"); request.set_Headers(httpHeader); request.set_ContentLength(bytes.get_Length()); // 写入并关闭请求体流 requestStream = request.GetRequestStream(); requestStream.Write(bytes, 0, bytes.get_Length()); requestStream.Flush(); requestStream.Close(); // 获取响应并读取内容 response = request.GetResponse(); responseStream = response.GetResponseStream(); streamReader = new System.IO.StreamReader(responseStream); responseJson = streamReader.ReadToEnd(); info(strFmt("响应结果: %1", responseJson)); } catch (Exception::CLRError) { ex = CLRInterop::getLastException().GetBaseException(); error(strFmt("调用失败: %1", ex.get_Message())); } finally { // 确保所有资源被正确释放 if (streamReader != null) streamReader.Close(); if (responseStream != null) responseStream.Close(); if (response != null) response.Close(); CodeAccessPermission::revertAssert(); } }
关键修复点说明
- Content-Type修正:将
text/html改为application/json,明确告知服务端请求体为JSON格式,这是解决Bad Request的核心修复项 - 自定义头部规范:移除头部名称中的空格(改为
Pass-Owner-Id格式),并补充对应业务值,符合HTTP头部键: 值的标准格式 - 资源释放优化:使用
finally块确保流和响应对象无论是否异常都会被关闭,避免资源泄漏 - Response实例修正:删除无效的
new System.Net.HttpWebResponse(),由request.GetResponse()返回合法的响应实例 - 冗余变量清理:删除未使用的变量,简化代码结构
推荐的现代方案:使用HttpClient
HttpWebRequest属于.NET旧版API,Dynamics 365 F&O中推荐使用System.Net.Http.HttpClient,代码更简洁且自带连接池优化:
public static void main(Args _args) { str destinationUrl = "https://xyz.com/api/your-endpoint"; str requestJson = '{"param1":"value1","param2":"value2"}'; str responseJson; System.Net.Http.HttpClient httpClient; System.Net.Http.StringContent content; System.Net.Http.HttpResponseMessage response; System.Exception ex; try { new InteropPermission(InteropKind::ClrInterop).assert(); httpClient = new System.Net.Http.HttpClient(); // 添加自定义头部 httpClient.DefaultRequestHeaders.Add("Pass-Owner-Id", "your-owner-id"); httpClient.DefaultRequestHeaders.Add("GSTIN", "your-gstin-value"); // 创建JSON请求内容 content = new System.Net.Http.StringContent(requestJson, System.Text.Encoding::get_UTF8(), "application/json"); // 发送POST请求并同步获取结果 response = httpClient.PostAsync(destinationUrl, content).Result; // 校验请求状态 if (response.IsSuccessStatusCode) { responseJson = response.Content.ReadAsStringAsync().Result; info(strFmt("响应结果: %1", responseJson)); } else { error(strFmt("请求失败,状态码: %1,原因: %2", response.StatusCode.ToString(), response.ReasonPhrase)); } } catch (Exception::CLRError) { ex = CLRInterop::getLastException().GetBaseException(); error(strFmt("调用异常: %1", ex.get_Message())); } finally { if (httpClient != null) httpClient.Dispose(); CodeAccessPermission::revertAssert(); } }
额外注意事项
- 需确保Dynamics 365环境已配置出站网络规则,允许访问目标域名(在LCS环境管理的网络配置中添加)
- 若目标API需要身份认证(如Bearer Token),需在头部添加
Authorization: Bearer {your-token} - 生产环境中若处理高并发请求,建议复用HttpClient实例而非每次创建,避免连接耗尽
内容的提问来源于stack exchange,提问作者ayushawasthi
相关产品推荐
相关产品推荐

