Skip to main content

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 := true
Registry calls Service.RPC(State) — your logic runs
|v
Mobile App
Receives JSON response and renders updated page
  1. The mobile app sends a JSON-RPC request containing a method, service, bundle, and input parameters.
  2. MobileRPCRegistry220FDW hydrates a MobileRPCState220FDW instance from the request.
  3. The registry looks up the Mobile Service Registry table to find the codeunit ID for the service code.
  4. The registry raises the OnResolveService event with that codeunit ID.
  5. Your event subscriber checks the ID, sets Service := this, and sets IsServiceResolved := true.
  6. The registry calls Service.RPC(State) on your codeunit.
  7. Your codeunit reads State.Method(), executes business logic, and returns a JsonObject.

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:

  1. Search for Mobile Service Setup
  2. Add a new line: Mobile Service Code = HELLOSERVICE, Codeunit Id = 50100

Step 4: Load the Page and Test

  1. Open Mobile Page for your App Bundle and create a page with Page ID = HELLO-PAGE
  2. Paste the page JSON into the Page Json field
  3. Set it as the Root Page ID in the App Bundle setup
  4. 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