You can call AL code from a codeunit from APD in two different ways:

      1. Codeunit Action

      1. Inline Codeunit tag

    Codeunit actions are typically used for calling business logic, such as processing or posting, and will at the end of the process, redirect the user to a new page/action.

    Inline codeunit tags enables you to procedure HTML output on the fly, this could be calculating a single value or outputting a complete HTML page (or anything in between).

    it’s up to you, to verify that parameters are within allowed values, APD will only ensure that the user is allowed to use the action. Security filters are not applied to anything that happens inside a codeunit. So validate all parameters before use.

    The codeunit must be called on the “APD Session Hgd” table that gives context and you can use function in the APD Worker Hgd codeunit to interact with the page, see the below example.

    codeunit 50100 "Web Site Functions"
    {
        TableNo = "APD Session Hgd";
    
        trigger OnRun()
        begin
            // Commands (Codeunit called from <?codeunit()?> tag
            CASE APD.GetParameter(Rec, 'parameter1') OF
                'CALCPRICE':
                    CalculatePrice(Rec);
                '':
                    BEGIN // Codeunit called directly from a action
                        CASE UPPERCASE(APD.GetParameter(Rec, 'action')) OF
                            'POST.INVOICE':
                                PostInvoice(Rec);
                            ELSE
                                APD.HttpHeader(0, '/', '', '', '');
                        END;
                    END;
            END;
        end;
    
        local procedure CalculatePrice(var Session: Record "APD Session")
        begin
            APD.StreamWrite('<strong>123.45</strong>');
        end;
    
        local procedure PostInvoice(var Session: Record "APD Session")
        var
             SH : Record  "Sales Header";
        begin
           SH.Get(SH."Document Type"::Invoice, APD.GetParameter(Session,'invoiceno'));
           // Now Post it!
           // Redirect to a "doneposting" action page
           APD.HttpHeader(0, '/wsfn/doneposting','','','');
        end;
    
        var
            APD: Codeunit "APD Worker Hgd";
    }

    local procedure ChangePassword(var Session: Record "APD Session Hgd")
        var
            CurrentPassword: Text;
            NewPassword1: Text;
            NewPassword2: Text;
            User: Record "APD User Hgd";
            PasswordError: Label 'Wrong information entered, please try again.';
        begin
     
            CurrentPassword := APD.GetParameter(Session, 'current');
            NewPassword1 := APD.GetParameter(Session, 'newpassword1');
            NewPassword2 := APD.GetParameter(Session, 'newpassword2');
     
            IF (LOWERCASE(CurrentPassword) = LOWERCASE(Session.Password)) AND
              (NewPassword1 <> '') AND
              (LOWERCASE(NewPassword1) = LOWERCASE(NewPassword2)) THEN BEGIN
                User.GET(Session.UserID);
                User.VALIDATE(Password, LOWERCASE(NewPassword1));
                User.MODIFY;
     
                APD.HttpHeader(0, APDPath, '', '', '');
            END ELSE
                APD.HttpHeader(0, APDPath + '?action=CHANGE.PASSWORD&_ERRORMESSAGE=' + PasswordError, '', '', '');
        end;

     

     Upload a file into Business Central

     This example shows how to upload a binary into APD, this example comes from a project portal where user can upload documents to a task:

    local procedure TaskUpload(var Session: Record "APD Session Hgd")
        var
            JobTask: Record "Job Task";
            OK: Boolean;
            OutS: OutStream;
            InS: InStream;
            Ref: RecordRef;
            Setup: Record "Web Setup";
            Log: Record "Job Task History";
        begin
            Setup.GET;
     
            JobTask.GET(APD.GetParameter(Session, '1001:1'), APD.GetParameter(Session, '1001:2'));
     
            VerifyJobAgainstUser(JobTask."Job No.", Session);
     
            Session.CALCFIELDS("Uploaded File");
            Session."Uploaded File".CREATEINSTREAM(InS);
     
            Log.INIT;
            Log."Job No." := JobTask."Job No.";
            Log."Job Task No." := JobTask."Job Task No.";
            Log.Log := APD.GetLocalDateTime(); // CURRENTDATETIME;
            Log.INSERT(TRUE);
            Log.Status := Setup."Status for Upload";
            Log.UploadData.CREATEOUTSTREAM(OutS);
            COPYSTREAM(OutS, InS);
            Log.Filename := Session."Uploaded File Name";
            Log."Web User" := Session.UserID;
            Log.MODIFY(TRUE);
     
            APD.HttpHeader(0, APDPath + '?action=TASK&1001:1=' + JobTask."Job No." +
                                        '&1001:2=' + JobTask."Job Task No.", '', '', '');
        end;

    Here is the template stub to go together with the upload code, see the multipart/form-data encoding of the form: 



    Change Password Example

     This example is a change password function:

    local procedure ChangePassword(var Session: Record "APD Session Hgd")
        var
            CurrentPassword: Text;
            NewPassword1: Text;
            NewPassword2: Text;
            User: Record "APD User Hgd";
            PasswordError: Label 'Wrong information entered, please try again.';
        begin
     
            CurrentPassword := APD.GetParameter(Session, 'current');
            NewPassword1 := APD.GetParameter(Session, 'newpassword1');
            NewPassword2 := APD.GetParameter(Session, 'newpassword2');
     
            IF (LOWERCASE(CurrentPassword) = LOWERCASE(Session.Password)) AND
              (NewPassword1 <> '') AND
              (LOWERCASE(NewPassword1) = LOWERCASE(NewPassword2)) THEN BEGIN
                User.GET(Session.UserID);
                User.VALIDATE(Password, LOWERCASE(NewPassword1));
                User.MODIFY;
     
                APD.HttpHeader(0, APDPath, '', '', '');
            END ELSE
                APD.HttpHeader(0, APDPath + '?action=CHANGE.PASSWORD&_ERRORMESSAGE=' + PasswordError, '', '', '');
        end;

     

     Upload a file into Business Central

     This example shows how to upload a binary into APD, this example comes from a project portal where user can upload documents to a task:

    local procedure TaskUpload(var Session: Record "APD Session Hgd")
        var
            JobTask: Record "Job Task";
            OK: Boolean;
            OutS: OutStream;
            InS: InStream;
            Ref: RecordRef;
            Setup: Record "Web Setup";
            Log: Record "Job Task History";
        begin
            Setup.GET;
     
            JobTask.GET(APD.GetParameter(Session, '1001:1'), APD.GetParameter(Session, '1001:2'));
     
            VerifyJobAgainstUser(JobTask."Job No.", Session);
     
            Session.CALCFIELDS("Uploaded File");
            Session."Uploaded File".CREATEINSTREAM(InS);
     
            Log.INIT;
            Log."Job No." := JobTask."Job No.";
            Log."Job Task No." := JobTask."Job Task No.";
            Log.Log := APD.GetLocalDateTime(); // CURRENTDATETIME;
            Log.INSERT(TRUE);
            Log.Status := Setup."Status for Upload";
            Log.UploadData.CREATEOUTSTREAM(OutS);
            COPYSTREAM(OutS, InS);
            Log.Filename := Session."Uploaded File Name";
            Log."Web User" := Session.UserID;
            Log.MODIFY(TRUE);
     
            APD.HttpHeader(0, APDPath + '?action=TASK&1001:1=' + JobTask."Job No." +
                                        '&1001:2=' + JobTask."Job Task No.", '', '', '');
        end;

    Here is the template stub to go together with the upload code, see the multipart/form-data encoding of the form: