--- title: "Extension points" slug: "bc-extension-points-devkit" tags: ["BC", "BIS", "Business Central", "Business Integration Solutions", "Concept", "Task"] updated: 2026-06-25T09:59:07Z published: 2026-06-25T09:59:07Z canonical: "docs.staedean.com/bc-extension-points-devkit" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.staedean.com/llms.txt > Use this file to discover all available pages before exploring further. # Extension points Extension points are specific places in the application where you can add or modify functionality without changing the base code. They let developers customize and extend the application in a modular and maintainable way. Two types of extension points exist: existing extension points and new extension points you can request. ## Existing extension points ### Internal Document import extension points `OnAfterMigrateFieldID`: the publisher `OnAfterMigrateFieldID` has a reference in the Internal Document import: ```plaintext procedure MigrateFieldId(BISVersion: Text; TableId: Integer; FieldId: Integer) NewFieldId: Integer var    Handled: Boolean; begin    OnAfterMigrateFieldID(BISVersion, TableId, FieldId, NewFieldId, Handled);    if not Handled then        NewFieldId := FieldId; end; [IntegrationEvent(false, false)] local procedure OnAfterMigrateFieldID(BISVersion: Text; TableId: Integer; OldFieldId: Integer; var NewFieldId: Integer; var Handled: Boolean) begin end; ``` Example usage: ```plaintext "BIS Document Line"."Field No." := TranslatorCU.MigrateFieldId(BISVersion, "BIS Document Line"."Table No.", "BIS Document Line"."Field No."); ``` `OnAfterMigrateObjectID`: the publisher `OnAfterMigrateObjectID` has references in the Internal Document import and in the Event Generator setup: ```plaintext procedure MigrateObjectId(BISVersion: Text; ObjType: ObjectType; OldObjectId: Integer) NewObjectId: Integer var    Handled: Boolean; begin    OnAfterMigrateObjectID(BISVersion, ObjType, OldObjectId, NewObjectId, Handled);    if not Handled then        OnAfterTranslateObjectID(ObjType, OldObjectId, NewObjectId, Handled);    if not Handled then        NewObjectId := OldObjectId; end; [IntegrationEvent(false, false)] local procedure OnAfterMigrateObjectID(BISVersion: Text; Type: ObjectType; OldId: Integer; var NewId: Integer; var Handled: Boolean) begin end; ``` Example usage: ```plaintext // In internal document: "BIS Document Line"."Table No." := TranslatorCU.MigrateObjectId(BISVersion, ObjectType::Table, "BIS Document Line"."Table No."); // In Event Generator XmlPort: "BIS Event Generator Setup"."Object ID to Run" := TranslateId.MigrateObjectId(BISVersion, ObjectType::Codeunit, "BIS Event Generator Setup"."Object ID to Run"); ``` ### Mapper import extension point `OnAfterMigrateExpression`: the publisher `OnAfterMigrateExpression` has a reference in the Mapping Expression XmlPort: ```plaintext procedure MigrateExpression(BISVersion: Text; Expression: Text) NewExpression: Text var    cuPos: integer;    lblCodeunit: text;    dotPos: integer;    CuID: integer;    newCuID: integer;    Result: Text;    Handled: Boolean; begin    lblCodeunit := 'codeunit:';    while Lowercase(Expression).Contains(lblCodeunit) do begin        cupos := Lowercase(Expression).indexof(lblCodeunit) + strlen(lblCodeunit) - 1;        Result += Expression.Substring(1, cupos);        Expression := copystr(Expression, cupos + 1);        dotPos := Expression.indexof('.');        if dotPos > 1 then            if evaluate(cuid, Expression.substring(1, dotpos - 1)) then begin                newcuid := MigrateObjectId(BISVersion, ObjectType::Codeunit, cuid);                if newcuid <> cuid then begin                    Result += format(newcuid);                    Expression := copystr(Expression, dotpos);                end;            end;    end;    Result += Expression;    OnAfterMigrateExpression(BISVersion, Result, NewExpression, Handled);    if not Handled then        NewExpression := Result; [IntegrationEvent(false, false)] local procedure OnAfterMigrateExpression(BISVersion: Text; Expression: Text; var NewExpression: Text; var Handled: Boolean) begin end; end; ``` Example usage: ```plaintext if VersionDec < 5.2 then    StreamExp := expression else begin    TempBlob.CreateOutStream(BCOutStream, TextEncoding::UTF8);    Base64Convert.FromBase64(expression, BCOutStream);    TempBlob.CreateInStream(BCInStream, TextEncoding::UTF8);    while not BCInStream.EOS() do begin        BCInStream.Read(StreamLine);        StreamExp += StreamLine;    end; end; StreamExp := Translator.MigrateExpression(BISVersion, StreamExp); "BIS Mapping Line".SaveExpression(StreamExp); ``` ### Mapper activity extension points `OnBeforeRunActivity`: lets you add custom logic or validation before the **Mapper** activity executes. The source used for mapping is in the message body, and `RecRef` contains the record reference setup: ```plaintext procedure RunActivity(var Message: Record "BIS Message Queue") var    MappingSetup: Record "BIS Document Mapping Setup";    RecRef: RecordRef; begin    OnBeforeRunActivity(Message, RecRef);    Message.ReadActivitySetup(RecRef);    RecRef.SetTable(MappingSetup);    ApplyMapping(MappingSetup, Message); end; [IntegrationEvent(false, false)] local procedure OnBeforeRunActivity(var Message: Record "BIS Message Queue"; var RecRef: RecordRef) begin end; ``` Example usage: ```plaintext MessageQueue.Get(Message.GetMessageQueueId()); MessageQueue.CalcFields("Message Body"); CODEUNIT.Run(CODEUNIT::"BIS Document Mapper", MessageQueue); ``` `OnAfterRunActivity`: lets you add custom logic or validation after the **Mapper** activity executes. The source used for mapping is in the message body, and `RecRef` contains the record reference setup: ```plaintext procedure RunActivity(var Message: Record "BIS Message Queue") var    MappingSetup: Record "BIS Document Mapping Setup";    RecRef: RecordRef; begin    OnBeforeRunActivity(Message, RecRef);    Message.ReadActivitySetup(RecRef);    RecRef.SetTable(MappingSetup);    ApplyMapping(MappingSetup, Message);    OnAfterRunActivity(Message, RecRef); end; [IntegrationEvent(false, false)] local procedure OnAfterRunActivity(var Message: Record "BIS Message Queue"; var RecRef: RecordRef) begin end; ``` Example usage: ```plaintext MessageQueue.Get(Message.GetMessageQueueId()); MessageQueue.CalcFields("Message Body"); CODEUNIT.Run(CODEUNIT::"BIS Document Mapper", MessageQueue); MessageQueue.Modify(); Message.Load(MessageQueue."Entry No."); ``` ## Request new extension points STAEDEAN is happy to accommodate new extension points in the product to assist and automate migration scenarios. For more information, see [Request new extension points](/business-central/docs/bc-how-to-request-an-extension-point-in-staedean-software). ## Related - [Mapping](/bc-bis-mapping.md) - [Request extension point in STAEDEAN - Business Central software](/bc-how-to-request-an-extension-point-in-staedean-software.md)