Creating a Mobile Service
In this tutorial you will build a complete Aptean Mesh mobile service from scratch — a custom "Hello World" service that returns a page with a header, body content, and an interactive button. By the end you will understand the full request/response cycle between the mobile app and Business Central.
Prerequisites
- A Business Central development environment with the Aptean Mesh base app installed
- An App Bundle configured in the Mobile App Bundle setup page
- Familiarity with AL codeunits and JSON in Business Central
How the Request Cycle Works
Service Resolution Flow
Mobile App
Sends JSON-RPC request
|v
BCRPC220FDW (API Page)
Receives request, delegates to registry
|v
MobileRPCRegistry220FDW
Looks up service code in Service Registry table
Fires
OnResolveService event with the Codeunit ID|v
Your Service Codeunit (implements IBCRPC220FDW)
Subscriber sets
Service := this and IsServiceResolved := trueRegistry calls
Service.RPC(State) — your logic runs|v
Mobile App
Receives JSON response and renders updated page
- The mobile app sends a JSON-RPC request containing a
method,service,bundle, andinputparameters. MobileRPCRegistry220FDWhydrates aMobileRPCState220FDWinstance from the request.- The registry looks up the Mobile Service Registry table to find the codeunit ID for the service code.
- The registry raises the
OnResolveServiceevent with that codeunit ID. - Your event subscriber checks the ID, sets
Service := this, and setsIsServiceResolved := true. - The registry calls
Service.RPC(State)on your codeunit. - Your codeunit reads
State.Method(), executes business logic, and returns aJsonObject.
Step 1: Create the Service Codeunit
namespace MyCompany.MeshDemo;
using Aptean.Mesh.SDUI;
codeunit 50100 HelloService implements IBCRPC220FDW
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::MobileRPCRegistry220FDW,
OnResolveService, '', false, false)]
local procedure ResolveHelloService(
CodeunitId: Integer;
var Service: Interface IBCRPC220FDW;
var IsServiceResolved: Boolean)
begin
if IsServiceResolved then
exit;
if CodeunitId = Codeunit::HelloService then begin
Service := this;
IsServiceResolved := true;
end;
end;
procedure RPC(var State: Codeunit MobileRPCState220FDW) ResponseJson: JsonObject
begin
case State.Method() of
'GetHelloPage':
exit(GetHelloPage(State));
'OnGreetTapped':
exit(OnGreetTapped(State));
end;
ResponseJson := State.Serialize();
end;
local procedure GetHelloPage(var State: Codeunit MobileRPCState220FDW) Result: JsonObject
begin
Result.Add('title', 'Welcome');
Result.Add('message', 'Hello from Business Central!');
Result.Add('timestamp', Format(CurrentDateTime, 0, 9));
end;
local procedure OnGreetTapped(var State: Codeunit MobileRPCState220FDW) Result: JsonObject
var
UserName: Text;
begin
UserName := State.GetInput('userName', false);
if UserName = '' then
UserName := UserId();
Result.Add('title', 'Greeting');
Result.Add('message', StrSubstNo('Hello, %1!', UserName));
Result.Add('timestamp', Format(CurrentDateTime, 0, 9));
end;
}
Key Points
State.Method()returns the method name sent by the mobile client.State.GetInput('userName', false)reads a named parameter from the client request. The second parameter (ShowError) controls whether a missing key raises an error or returns an empty string.State.Serialize()serializes the current RPC state back as a response, including any commands or workflow state.
Step 2: Define the Page JSON
{
"pageId": "HELLO-PAGE",
"service": "HELLOSERVICE",
"header": {
"title": {
"type": "text",
"props": {
"valueKey": "title",
"variant": "TITLE"
}
}
},
"body": [
{
"type": "text",
"props": { "valueKey": "message", "variant": "BODY" }
},
{
"type": "card",
"props": {
"title": "Service Info",
"fields": [{ "label": "Last Updated", "valueKey": "timestamp" }]
}
},
{
"type": "button",
"props": { "label": "Greet Me", "actionId": "greetAction" }
}
],
"dataContract": {
"initialActionId": "loadPage",
"actions": [
{ "id": "loadPage", "type": "api", "endpoint": "GetHelloPage", "params": [] },
{ "id": "greetAction", "type": "api", "endpoint": "OnGreetTapped", "params": ["userName"] }
]
}
}
Step 3: Register in the Mobile Service Registry
In Business Central:
- Search for Mobile Service Setup
- Add a new line: Mobile Service Code =
HELLOSERVICE, Codeunit Id =50100
Step 4: Load the Page and Test
- Open Mobile Page for your App Bundle and create a page with Page ID =
HELLO-PAGE - Paste the page JSON into the Page Json field
- Set it as the Root Page ID in the App Bundle setup
- Launch the mobile app and sign in
Production Example
See ReceiptService220FDW in the Aptean Mesh base app for a production example. It implements both IBCRPC220FDW and IStepHandler220FDW and handles Initialize, HandleWorkFlow, UndoStep, and PrintLabel.
Summary
You created a service codeunit, subscribed to OnResolveService, routed RPC methods, defined a JSON page, and registered the service in the Mobile Service Registry.
What's Next
- Page with Data Binding — query BC data and bind it to page components
- Internationalization — translate your UI labels for multi-language warehouses