Business Central中Postman提交Blob(JSON子类型)数据报错求助
Business Central API Blob(JSON)字段流未关闭错误排查与解决方案
问题概述
在Business Central中创建了包含Blob(JSON子类型)字段的表sch_schedulerconfiguration,通过Postman向其API端点提交数据时,收到错误:"Read called with an open stream or text reader..."。
- 请求地址:
https://api.businesscentral.dynamics.com/v2.0/{TenantID}/Sandbox/api/CJAPI/CJG/v1.0/companies({CompanyID})/sch_schedulerconfiguration - 请求体包含
sch_bookingform、sch_hoverdetails、sch_popupdetails等Blob字段的JSON字符串
现有实现
- 表中Blob字段配置了
OnValidate触发器,用于检查值是否存在 - Codeunit
SchedulerConfigurationHandler包含WriteJSONToBlob和ReadJSONFromBlob方法,处理流的读写操作 - API Page
schedulerconfiguration将该表暴露为API端点
1. 错误原因排查
错误核心是流资源未正确释放,常见触发场景:
- 自定义流处理方法(
WriteJSONToBlob/ReadJSONFromBlob)中,打开的InStream/OutStream未调用Close()方法,也未用with语句自动回收资源,导致流长期处于打开状态,与API的后续读取操作冲突 OnValidate触发器中直接操作流但未关闭,导致API处理时流被占用- API Page中Blob字段的类型映射错误,未正确适配JSON子类型的序列化逻辑,引发流生命周期管理异常
2. API处理Blob(JSON)字段的正确方式
- 优先使用Business Central原生的**Blob(JSON子类型)**支持:该类型可直接存储JSON数据,API会自动完成序列化/反序列化,无需手动处理流
- 若必须自定义流操作,需保证流操作的原子性:打开流→完成读写→立即关闭,禁止跨操作保持流打开
- API Page中需明确Blob字段的
DataType=Blob、SubType=JSON,确保API识别其JSON属性
3. 现有实现修改方案
方案1:移除自定义流处理,使用原生Blob(JSON)支持(推荐)
此方案最简洁,利用BC原生能力避免流管理问题:
- 表字段配置:保持
Blob类型,SubType设为JSON - 修改OnValidate触发器:直接检查Blob大小,无需操作流
trigger OnValidate() begin if Rec."sch_bookingform".Size = 0 then Error('Booking form JSON cannot be empty'); end; - API Page字段定义:
field(sch_bookingform; Rec."sch_bookingform") { Caption = 'Booking Form'; DataType = Blob; SubType = JSON; } - Postman请求体格式:直接提交JSON对象(无需转成字符串)
{ "sch_bookingform": { "field1": "value1", "field2": "value2" }, "sch_hoverdetails": {"key": "value"}, "sch_popupdetails": {"key": "value"} }
方案2:保留自定义流处理,修复流生命周期
若需保留原有流处理逻辑,需强制保证流的关闭:
- 修改流处理方法:
procedure WriteJSONToBlob(var BlobField: Blob; JSONText: Text) var OutStream: OutStream; begin BlobField.CreateOutStream(OutStream); OutStream.WriteText(JSONText); OutStream.Close(); // 必须显式关闭流 end; procedure ReadJSONFromBlob(var BlobField: Blob): Text var InStream: InStream; JSONText: Text; begin BlobField.CreateInStream(InStream); InStream.ReadText(JSONText); InStream.Close(); // 必须显式关闭流 exit(JSONText); end; - API Page添加计算字段:暴露字符串格式的JSON供API调用,避免直接操作Blob流
field(sch_bookingform_text; GetBookingFormJSON()) { Caption = 'Booking Form JSON'; DataType = Text; Editable = true; } local procedure GetBookingFormJSON(): Text var SchedulerConfigHandler: Codeunit SchedulerConfigurationHandler; begin exit(SchedulerConfigHandler.ReadJSONFromBlob(Rec."sch_bookingform")); end; trigger OnModify() var SchedulerConfigHandler: Codeunit SchedulerConfigurationHandler; begin if Rec."sch_bookingform_text" <> '' then SchedulerConfigHandler.WriteJSONToBlob(Rec."sch_bookingform", Rec."sch_bookingform_text"); end; - Postman请求体格式:提交转义后的JSON字符串
{ "sch_bookingform_text": "{\"field1\":\"value1\",\"field2\":\"value2\"}", "sch_hoverdetails_text": "{\"key\":\"value\"}", "sch_popupdetails_text": "{\"key\":\"value\"}" }
验证步骤
- 用Postman发送POST请求,确认错误消失
- 调用GET API验证Blob字段的JSON数据正确返回
- 查看Business Central表中数据存储正常
内容的提问来源于stack exchange,提问作者Parth Sukhadiya
相关产品推荐
相关产品推荐

