Advanced Portal Designer Documentation
Index

File Script Action

File Script actions combine HTML templates with embedded AL code, offering the best of both File and Script action types.

Overview

A File Script action:

  • Uses HTML/template syntax for structure
  • Embeds AL code blocks for logic
  • Compiles to executable form
  • Provides dynamic content generation

When to Use File Script Actions

Use File Script actions for:

  • Pages with complex logic embedded in HTML
  • Dynamic content that needs AL processing
  • Templates requiring calculations
  • Mixed static and dynamic content

Creating a File Script Action

Step-by-Step

  1. Open the Advanced Portal Designer menu page (search for it in Tell Me) and click Actions
  2. Click New
  3. Enter the Web Action code
  4. Set Type to "File Script"
  5. Click the "Edit Script" link
  6. Write your HTML with embedded AL
  7. Save and compile

Syntax

Basic Structure

<?bc
// AL code block - declarations and setup
var
    Customer: Record Customer;
    CustomerName: Text;
?>

<!DOCTYPE html>
<html>
<head>
    <title>Customer Page</title>
</head>
<body>
    <?bc
    Customer.FindFirst();
    CustomerName := Customer.Name;
    ?>
    
    <h1>Welcome, <?bc output(CustomerName); ?></h1>
</body>
</html>

The <?bc ?> Tag

AL code is wrapped in <?bc ?> tags:

  • First block: Must start with <?bc - sets up the script context
  • Subsequent blocks: Contain AL code to execute
  • Output: Use output() to insert content

Script Functions Reference

File Script actions have access to the same additional AL commands as Script actions. These can be used inside <?bc ?> blocks:

Function Description
output(<text>) Send text/HTML content into the page at the current position
response(<html/redirect>,<ContentType>,<RedirectLink>) Set the response type - use to return specific content types or redirect the user
parm(<parameter>) Get a parameter value from the query string or POST data
action(<name>,[Record Variable]) Navigate to another action, optionally passing a record variable
currentuserid() Get the current APD user ID
setlanguage(<language no>) Set the language for the response
updatesession(<Type>,<Number>,'',<Security Profiles Filter>) Update the current session. Type: 1=Customer, 2=Vendor, 3=Contact, 4=Salesperson
stripestatus(<Stripe Session>,<SettingToGet>) Get the status of a Stripe payment session

For detailed descriptions and examples of each function, see the Script Action documentation.

Code Blocks

Declaration Block

The first <?bc ?> block typically contains variable declarations:

<?bc
var
    Customer: Record Customer;
    Items: Record Item;
    Total: Decimal;
    Html: TextBuilder;
?>

Logic Blocks

Subsequent blocks contain executable code:

<?bc
Customer.Get('10000');
Total := Customer."Balance (LCY)";
?>

Inline Output

Use output() within HTML context:

<p>Customer: <?bc output(Customer.Name); ?></p>
<p>Balance: <?bc output(format(Total, 0, '<Precision,2:2>')); ?></p>

Complete Example

<?bc
var
    SalesHeader: Record "Sales Header";
    SalesLine: Record "Sales Line";
    OrderTotal: Decimal;
?>

<!DOCTYPE html>
<html>
<head>
    <title>My Orders</title>
    <style>
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; }
    </style>
</head>
<body>
    <h1>Your Orders</h1>
    
    <table>
        <tr>
            <th>Order No.</th>
            <th>Date</th>
            <th>Amount</th>
        </tr>
        
        <?bc
        SalesHeader.SetRange("Document Type", SalesHeader."Document Type"::Order);
        SalesHeader.SetRange("Sell-to Customer No.", Rec."Navision number");
        
        if SalesHeader.FindSet() then
            repeat
                SalesHeader.CalcFields("Amount Including VAT");
                ?>
                <tr>
                    <td><?bc output(SalesHeader."No."); ?></td>
                    <td><?bc output(format(SalesHeader."Order Date")); ?></td>
                    <td><?bc output(format(SalesHeader."Amount Including VAT", 0, '<Precision,2:2>')); ?></td>
                </tr>
                <?bc
                OrderTotal += SalesHeader."Amount Including VAT";
            until SalesHeader.Next() = 0;
        ?>
    </table>
    
    <p><strong>Total: <?bc output(format(OrderTotal, 0, '<Precision,2:2>')); ?></strong></p>
</body>
</html>

Conditional Content

If Statements

<?bc
if Rec."User Authenticated" then
    ?>
    <p>Welcome back, <?bc output(Rec.UserID); ?>!</p>
    <?bc
else
    ?>
    <p>Please <a href="?action=LOGIN">log in</a>.</p>
    <?bc
end;
?>

Shorter Form

<?bc if Customer."Balance (LCY)" > 0 then ?>
    <p class="positive"><?bc output(format(Customer."Balance (LCY)")); ?></p>
<?bc else ?>
    <p class="zero">No balance</p>
<?bc end; ?>

Loops

Repeat Loop

<ul>
<?bc
if Item.FindSet() then
    repeat ?>
        <li><?bc output(Item.Description); ?></li>
    <?bc until Item.Next() = 0;
?>
</ul>

Building Tables

<table>
<?bc
Customer.FindSet();
repeat ?>
    <tr>
        <td><?bc output(Customer."No."); ?></td>
        <td><?bc output(Customer.Name); ?></td>
    </tr>
<?bc until Customer.Next() = 0; ?>
</table>

Accessing Parameters

Session Data

<?bc
// Access session record via Rec
var
    CustomerNo: Code[20];
?>

<?bc
CustomerNo := Rec."Navision number";
?>

<p>Your customer number: <?bc output(CustomerNo); ?></p>

URL Parameters

<?bc
var
    OrderNo: Code[20];
?>

<?bc
OrderNo := parm('orderno');
?>

<h1>Order: <?bc output(OrderNo); ?></h1>

HTML Escaping

When outputting user data, consider HTML escaping to prevent XSS:

<?bc
// Use a helper function to escape HTML
var
    UserInput: Text;
    SafeOutput: Text;
?>

<?bc
UserInput := parm('search');
SafeOutput := UserInput.Replace('<', '&lt;').Replace('>', '&gt;');
?>

<p>Search term: <?bc output(SafeOutput); ?></p>

Comparison with Other Types

Feature File Script File Script
HTML structure Yes Manual Yes
AL code Tags only Full Embedded
Complex logic Limited Yes Yes
Template reuse Yes No Limited
Best for Simple pages APIs Dynamic pages

Best Practices

Separate Concerns

Keep logic minimal in the template:

<?bc
// Do complex logic in one block
var
    Data: Text;
?>

<?bc
// Prepare all data first
Data := PrepareComplexData();
?>

<!-- Then just output in HTML -->
<p><?bc output(Data); ?></p>

Error Handling

<?bc
var
    HasError: Boolean;
    ErrorMsg: Text;
?>

<?bc
if not TryLoadData() then begin
    HasError := true;
    ErrorMsg := GetLastErrorText();
end;
?>

<?bc if HasError then ?>
    <div class="error"><?bc output(ErrorMsg); ?></div>
<?bc else ?>
    <!-- Normal content -->
<?bc end; ?>

Performance

  • Minimize database calls within loops
  • Prepare data before output
  • Use appropriate filters

Compilation

Requirements

File Script actions require compilation:

  1. Click the compile action
  2. Review any errors
  3. Test the page

Common Errors

Error Cause Solution
Unclosed Missing ?> Add closing ?>
Unexpected code AL outside Wrap in
Missing begin First block issue Check structure

Debugging

Tips for Debugging

  1. Start with simple content
  2. Add logic incrementally
  3. Use output() for debug values
  4. Check compilation errors carefully

Debug Output

<?bc
// Temporary debug output
output('DEBUG: Customer count = ' + format(Customer.Count));
?>