Sunday, December 10, 2023

Debug Web Service (SOAP or REST), Job Queue and User Session

 Hello Friend

Business Central provide facility to debug any of below session in Production or Sandbox environment in On-Prime Version

 - Any User Session

- Web Service Session (SOAP or REST)

- Job Queue Session

More details available on this blog:

https://arquiconsult.com/en/debug-attach/

https://yzhums.com/35078/

Finding and fixing bugs or errors is part of our daily tasks. This process may take a lot of time if we do not use the debugger and, even more, if the error occurs in a Web Service or in a Job Queue task.

In the older versions, the solution was to use the “Debug Next” functionality, but in Visual Studio Code that functionality is not present. No problem, we’ll use Attach.

To Enable debug we need User ID or Session ID

  Setting              Description
userId                            The GUID of the user on whose behalf a snapshot debugging will be started. For on-premises, this can also be the user name in user password authentication scenarios. The user must be able to start, or have a session type opened that is specified in the breakOnNext parameter. For more information, see JSON Files.
sessionId                                       A session ID for the user specified above in userId.

In request parameter we can setup either "launch" or "attach"

Below are few example of configuration to setup in launch.json:

1) For Debug any Web Service session in BC SaaS

{
    "name": "Webservice_Debug",
    "type": "al",
    "request": "attach",
    "environmentType": "Sandbox",
    "environmentName": "AmericasDev",            
    "breakOnError": "All",          
    "tenant": "2474247c-aa32-48ba-b9a0-38e470449497",
    "breakOnNext": "WebServiceClient",
    "userId": "OAUTH_BC"          
}

2) For Debug any User Session in BC On Prime

{
    "name": "UserSessionDebg_Debug",
    "type": "al",
    "request": "attach",
    "server": "http://10.110.98.168:8080/",
    "serverInstance": "T002",
    "port": 2749,
    "authentication":"Windows",
    "breakOnError": "All",              
    "breakOnNext": "WebClient",
    "sessionId":9589    
}

3) For Debug Job Queue Session in BC on prime

{
    "name": "JobQueue_Debug",
    "type": "al",
    "request": "attach",
    "server": "http://10.110.98.168:8080/",
    "serverInstance": "T002",
    "port": 2749,
    "authentication":"Windows",
    "breakOnError": "All",              
    "breakOnRecordWrite": "None",    
    "breakOnNext": "Background"
}

4) Debug webservice session in BC on prime

{
    "name": "Webservice_Debug_OnPrime",
    "type": "al",
    "request": "attach",
    "server": "http://10.110.98.168:8080/",
    "serverInstance": "T002",
    "port": 2749,
    "breakOnError": "All",              
    "breakOnNext": "WebServiceClient",
    "userId": "OAUTH_BC"          
}  

You can fine the Session ID in BC from front end.

Goto Help and Support and at bottom you can view session id





















Similar you can get it from BC Admin center



















































For BC on Prime we can create page from table "Active Session" where you can see the session and instance name of us


Action Session Page AL Source:

page 50571 "DEV Kill Session"
{
    ApplicationArea = All;
    Caption = 'Kill Sessions (Danger)';
    Editable = true;
    PageType = List;
    SourceTable = "Active Session";
    UsageCategory = Tasks;
    InsertAllowed = false;
    ModifyAllowed = false;

    layout
    {
        area(Content)
        {
            repeater(Group)
            {
                field("User ID"; Rec."User ID")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the User ID field';
                }
                field("Session ID"; Rec."Session ID")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Session ID field';
                }
                field("Login Datetime"; Rec."Login Datetime")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Login Datetime field';
                }

                field("Client Type"; Rec."Client Type")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Client Type field';
                }
                field("Client Computer Name"; Rec."Client Computer Name")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Client Computer Name field';
                }
                field("Server Instance ID"; Rec."Server Instance ID")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Server Instance ID field';
                }
                field("Server Instance Name"; Rec."Server Instance Name")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Server Instance Name field';
                }
                field("Database Name"; Rec."Database Name")
                {
                    ApplicationArea = All;
                    StyleExpr = StyleExp;
                    ToolTip = 'Specifies the value of the Database Name field';
                }
            }
        }
    }

    actions
    {
        area(Processing)
        {
            action(Kill)
            {
                ApplicationArea = All;
                Caption = 'Kill Session';
                Image = Stop;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                PromotedOnly = true;
                ToolTip = 'Kill selected session';

                trigger OnAction();
                var
                    KillMsg: Text;
                    KillLbl: Label '%1 killed your current session.', Comment = '%1 User Id';
                begin
                    if Rec."Session ID" = SessionId() then
                        exit;

                    KillMsg := StrSubstNo(KillLbl, UserID());
                    ClearLastError();
                    if not StopSession(Rec."Session ID", KillMsg) then
                        Error(GetLastErrorText);
                end;
            }

            action(Delete)
            {
                ApplicationArea = All;
                Caption = 'Delete Session';
                Image = Stop;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                PromotedOnly = true;

                trigger OnAction();
                var
                    KillMsg: Text;
                    KillLbl: Label '%1 killed your current session.', Comment = '%1 User Id';
                begin
                    if Rec."Session ID" = SessionId() then
                        exit;

                    Rec.Delete(TRUE);
                end;
            }

            action(Kill_Selected)
            {
                ApplicationArea = All;
                Caption = 'Kill Session (Selected Record)';
                Image = Stop;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                PromotedOnly = true;
                ToolTip = 'Kill selected session';

                trigger OnAction();
                var
                    KillMsg: Text;
                    KillLbl: Label '%1 killed your current session.', Comment = '%1 User Id';
                begin
                    Killrec();
                end;
            }

            action(Delete_Selected)
            {
                ApplicationArea = All;
                Caption = 'Delete Session (Selected Record)';
                Image = Stop;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                PromotedOnly = true;
                ToolTip = 'Delete Selected Session';

                trigger OnAction();
                var
                    KillMsg: Text;
                    KillLbl: Label '%1 killed your current session.', Comment = '%1 User Id';
                begin
                    Deleterec();
                end;
            }
        }
    }

    trigger OnAfterGetRecord()
    begin
        StyleExp := 'standard';
        if Rec."Session ID" = SessionId() then
            StyleExp := 'strong';
    end;

    local procedure Killrec()
    var
        RecKill: Record "Active Session";

        KillMsg: Text;
        KillLbl: Label '%1 killed your current session.', Comment = '%1 User Id';
    begin
        CurrPage.SetSelectionFilter(RecKill);
        IF RecKill.FindSet() Then begin
            repeat
                if RecKill."Session ID" <> SessionId() then begin

                    KillMsg := StrSubstNo(KillLbl, UserID());
                    ClearLastError();
                    if not StopSession(RecKill."Session ID", KillMsg) then
                        Error(GetLastErrorText);
                End;
            until RecKill.Next() = 0;
        end;

    end;


    local procedure Deleterec()
    var
        DelRec: Record "Active Session";

    begin
        CurrPage.SetSelectionFilter(DelRec);
        IF DelRec.FindSet() Then begin
            repeat
                if DelRec."Session ID" <> SessionId() then begin
                    DelRec.Delete(TRUE);
                End;
            until DelRec.Next() = 0;
        end;

    end;

    var
        StyleExp: Text;
}

Done.
I hope it will help someone

Thank you for reading.
Keep Sharing.....Keep Growing....

No comments:

Post a Comment