Skip to main content

Notifications

Announcements

No record found.

Small and medium business | Business Central, N...
Suggested answer

Posting JSON Data in Blob Data Type Using Postman in Business Central

(1) ShareShare
ReportReport
Posted on by 4

I have created a table in Business Central that includes fields with the Blob data type. When I try to send JSON data to these fields using Postman, I encounter the following error:

Postman API Call:
POST https://api.businesscentral.dynamics.com/v2.0/{TenantID}/Sandbox/api/CJAPI/CJG/v1.0/companies({CompanyID})/sch_schedulerconfiguration

Request Body:
{
"sch_bookingform": "{\"default\": \"booking test 13\"}",
"sch_configurationname": "Default test 15",
"sch_hoverdetails": "{\"tooltip\": \"Appointment Details\"}",
"sch_popupdetails": "{\"title\": \"Booking Info\", \"content\": \"Details about the booking\"}"
}
 

Error Response:

{
"error": {
"code": "BadRequest",
"message": "Read called with an open stream or text reader. Please close any open streams or text readers before calling Read. CorrelationId: dded16d1-6f2f-4415-8ea3-16601153746c."
}
}

Implementation Details

I have the following setup:

Table (sch_schedulerconfiguration)

  • The fields sch_bookingform, sch_hoverdetails, and sch_popupdetails are Blob type with Json subtype.
  • Each Blob field has an OnValidate trigger checking if a value exists.

Codeunit (SchedulerConfigurationHandler)

  • WriteJSONToBlob clears the Blob field, commits the change, and then writes the JSON data into an OutStream.
  • ReadJSONFromBlob reads the JSON data from an InStream.

API Page (schedulerconfiguration)

  • Exposes sch_schedulerconfiguration as an API endpoint.

Issue & Assistance Required

  • Why am I receiving the error "Read called with an open stream or text reader" when posting JSON data?
  • Is there a proper way to handle JSON in Blob fields via API requests?
  • Any suggestions to modify my implementation so that the API correctly stores and retrieves JSON data in Blob fields?
 

 

table 80100 sch_schedulerconfiguration
{
    DataClassification = ToBeClassified;
    Caption = 'Scheduler Configuration';
    fields
    {
        field(1; sch_configurationname; Text[50])
        {
            DataClassification = ToBeClassified;
            Caption = 'Configuarion Unique Name';
        }
        field(13; sch_bookingform; Blob)
        {
            DataClassification = ToBeClassified;
            Caption = 'Booking Form JSON';
            Subtype = Json;
 
            trigger OnValidate()
            var
                // JSONHandler: Codeunit JSONHandler;
                BookingJSON: Text;
            begin
                // BookingJSON := JSONHandler.GetBookingForm(Rec);
 
                if sch_bookingform.HasValue = true then
                    Error('Booking Form JSON is required.');
            end;
        }
        field(14; sch_hoverdetails; Blob)
        {
            DataClassification = ToBeClassified;
            Caption = 'Hover Details JSON';
            Subtype = Json;
            trigger OnValidate()
            begin
                if sch_hoverdetails.HasValue = true then
                    Error('Hover Details JSON is required.');
            end;
        }
        field(15; sch_popupdetails; Blob)
        {
            DataClassification = ToBeClassified;
            Caption = 'Popup Details JSON';
            Subtype = Json;
            trigger OnValidate()
            begin
                if sch_popupdetails.HasValue = true then
                    Error('Popup Details JSON is required.');
            end;
        }
 
    }
    keys
    {
        key(Key1; sch_configurationname)
        {
            Clustered = true;
        }
    }
    procedure GetBookingFormJSON(): Text
    var
        ConfigHandler: Codeunit SchedulerConfigurationHandler;
    begin
        exit(ConfigHandler.ReadJSONFromBlob(Rec, 'sch_bookingform'));
    end;
 
    procedure GetHoverDetailsJSON(): Text
    var
        ConfigHandler: Codeunit SchedulerConfigurationHandler;
    begin
        exit(ConfigHandler.ReadJSONFromBlob(Rec, 'sch_hoverdetails'));
    end;
 
    procedure GetPopupDetailsJSON(): Text
    var
        ConfigHandler: Codeunit SchedulerConfigurationHandler;
    begin
        exit(ConfigHandler.ReadJSONFromBlob(Rec, 'sch_popupdetails'));
    end;
 
}
codeunit 80103 SchedulerConfigurationHandler
{
    SingleInstance = false;
    procedure WriteJSONToBlob(var Rec: Record sch_schedulerconfiguration; JSONData: Text; FieldName: Text)
    var
        OutStream: OutStream;
    begin
        // ----- Step 1: Clear the Blob field and commit the change -----
        case FieldName of
            'sch_bookingform':
                Clear(Rec.sch_bookingform);
            'sch_hoverdetails':
                Clear(Rec.sch_hoverdetails);
            'sch_popupdetails':
                Clear(Rec.sch_popupdetails);
            else
                Error('Invalid field name');
        end;
 
        // First modify to persist the cleared Blob field.
        Rec.Modify(true);
        // Optionally, commit the transaction here to force closure of any open streams.
        COMMIT;
 
        // ----- Step 2: Open a new OutStream and write the JSON data -----
        case FieldName of
            'sch_bookingform':
                Rec.sch_bookingform.CreateOutStream(OutStream);
            'sch_hoverdetails':
                Rec.sch_hoverdetails.CreateOutStream(OutStream);
            'sch_popupdetails':
                Rec.sch_popupdetails.CreateOutStream(OutStream);
            else
                Error('Invalid field name');
        end;
 
        OutStream.WriteText(JSONData);
        // OutStream goes out of scope here, which should close it.
 
        // Save the updated Blob data.
        Rec.Modify(true);
    end;
 
    procedure ReadJSONFromBlob(var Rec: Record sch_schedulerconfiguration; FieldName: Text): Text
    var
        InStream: InStream;
        JSONData: Text;
    begin
        JSONData := ''; // Initialize to avoid null errors.
 
        // Ensure the correct field's stream is created
        case FieldName of
            'sch_bookingform':
                if Rec.sch_bookingform.HasValue then
                    Rec.sch_bookingform.CreateInStream(InStream);
            'sch_hoverdetails':
                if Rec.sch_hoverdetails.HasValue then
                    Rec.sch_hoverdetails.CreateInStream(InStream);
            'sch_popupdetails':
                if Rec.sch_popupdetails.HasValue then
                    Rec.sch_popupdetails.CreateInStream(InStream);
            else
                Error('Invalid field name');
        end;
 
        // Ensure InStream is not null before reading
        if not Rec.sch_bookingform.HasValue then
            exit(''); // If there's no value in the field, return an empty string
 
        InStream.ReadText(JSONData);
 
        exit(JSONData);
    end;
}
 
page 80100 schedulerconfiguration
{
    APIGroup = 'CJG';
    APIPublisher = 'CJAPI';
    APIVersion = 'v1.0';
    ApplicationArea = All;
    Caption = 'schedulerconfiguration';
    DelayedInsert = true;
    EntityName = 'sch_schedulerconfiguration';
    EntitySetName = 'sch_schedulerconfiguration';
    PageType = API;
    SourceTable = sch_schedulerconfiguration;
 
    layout
    {
        area(Content)
        {
            repeater(General)
            {
                field(sch_configurationname; Rec.sch_configurationname)
                {
                    Caption = 'Configuarion Unique Name';
                }
 
                field(sch_bookingform; Rec.sch_bookingform)
                {
                    Caption = 'Booking Form JSON';
                }
                field(sch_hoverdetails; Rec.sch_hoverdetails)
                {
                    Caption = 'Hover Details JSON';
                }
                field(sch_popupdetails; Rec.sch_popupdetails)
                {
                    Caption = 'Popup Details JSON';
                }
            }
        }
    }
    actions
    {
        area(Processing)
        {
            action(Save)
            {
                ApplicationArea = All;
                Caption = 'Save';
                Image = Save;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                ToolTip = 'Save the JSON data to the configuration.';
 
                trigger OnAction()
                var
                    ConfigHandler: Codeunit SchedulerConfigurationHandler;
                begin
                    // Save each JSON field to the corresponding Blob
                    ConfigHandler.WriteJSONToBlob(Rec, BookingFormJSONVar, 'sch_bookingform');
                    ConfigHandler.WriteJSONToBlob(Rec, HoverDetailsJSONVar, 'sch_hoverdetails');
                    ConfigHandler.WriteJSONToBlob(Rec, PopupDetailsJSONVar, 'sch_popupdetails');
                    Message('Configuration saved successfully.');
                end;
            }
        }
    }
 
    var
        BookingFormJSONVar: Text;
        HoverDetailsJSONVar: Text;
        PopupDetailsJSONVar: Text;
 
    trigger OnAfterGetRecord()
    begin
        // Load current Blob data into variables when the record is loaded
        BookingFormJSONVar := Rec.GetBookingFormJSON();
        HoverDetailsJSONVar := Rec.GetHoverDetailsJSON();
        PopupDetailsJSONVar := Rec.GetPopupDetailsJSON();
    end;
}
Any guidance would be greatly appreciated!
  • Suggested answer
    Bilal Haider Profile Picture
    Bilal Haider 193 on at
    Posting JSON Data in Blob Data Type Using Postman in Business Central
    Hi,
     
    I have gone through your example and I can see there are few changes you need to make.
     
    You should use unbounded action in this case. Copy the code from action Save and transfer to a codeunit procedure. You cannot insert data to blob directly using page api.
     
    Use the Yun Zhu's comment and go through the information on link to understand unbounded actions.
     
    Also you might need to change your input json as system expects only text data.
     
    Do these changes and then come back with the results.
  • Suggested answer
    YUN ZHU Profile Picture
    YUN ZHU 77,515 Super User 2025 Season 1 on at
    Posting JSON Data in Blob Data Type Using Postman in Business Central
    Sorry I haven't tested your example in detail.
    You can try the following method.
    Dynamics 365 Business Central: Using OData V4 unbound action (Codeunit API?) to communicate and exchange data seamlessly
     
    Thanks.
    ZHU
  • Suggested answer
    gdrenteria Profile Picture
    gdrenteria 14,174 Most Valuable Professional on at
    Posting JSON Data in Blob Data Type Using Postman in Business Central

    Hi, good day
    I hope this can help you, and give you some hints.

    Dynamics 365 Business Central: handling BLOB fields on APIs – Stefano Demiliani

    Best Regards
    Gerardo

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Vahid Ghafarpour – Community Spotlight

We are excited to recognize Vahid Ghafarpour as our February 2025 Community…

Congratulations to the January Top 10 leaders!

Check out the January community rock stars...

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 292,286 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 231,064 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans