Creating a Custom JSON Service in D365FO
This guide explains how to create a custom service in Dynamics 365 Finance and Operations (D365FO) that returns a list of customer balances in JSON format. It covers:
1. Overview
Custom services in D365FO allow you to expose business logic as RESTful endpoints. By using [DataContract] and [DataMember] attributes, D365FO handles JSON serialization/deserialization automatically.
In this example I'll expose a service to get a customer's balance and phone number for a specific customer group from a legal entity.
2. Request Data Contract
Defines the input parameters for the service: company and customer group.
[DataContract]
final class SIMIntegrationCustomerBalanceInfoRequest
{
private DataAreaId dataAreaId;
private CustGroupId custGroupId;
[DataMember("Company")]
public str parmDataAreaId(str _value = dataAreaId)
{
if (!prmIsDefault(_value)) dataAreaId = _value;
return dataAreaId;
}
[DataMember("CustomerGroup")]
public str parmCustGroupId(str _value = custGroupId)
{
if (!prmIsDefault(_value)) custGroupId = _value;
return custGroupId;
}
}
3. Response Data Contract
Defines the structure of the customer record returned by the service.
[DataContract]
final class SIMIntegrationCustomerBalanceInfoResponse
{
CustAccount customerAccount;
Name customerName;
AmountMST balance;
Phone phone;
[DataMember("CustomerAccount")]
public str parmCustomerAccount(str _customerAccount = customerAccount)
{
customerAccount = _customerAccount;
return customerAccount;
}
[DataMember("CustomerName")]
public str parmCustomerName(str _customerName = customerName)
{
customerName = _customerName;
return customerName;
}
[DataMember("Balance")]
public real parmBalance(real _balance = balance)
{
balance = _balance;
return balance;
}
[DataMember("Phone")]
public phone parmPhone(phone _phone = phone)
{
phone = _phone;
return phone;
}
}
4. Response List Contract
Wraps the response list for proper JSON serialization.
[DataContract]
final class SIMIntegrationCustomerBalanceInfoResponseList
{
List customerBalances;
[DataMember("customerBalances"),
AifCollectionType("_customerBalances", Types::Class, classStr(SIMIntegrationCustomerBalanceInfoResponse)),
AifCollectionType("return", Types::Class, classStr(SIMIntegrationCustomerBalanceInfoResponse))]
public List parmCustomerBalances(List _customerBalances = customerBalances)
{
customerBalances = _customerBalances;
return customerBalances;
}
}
5. Service Class
Contains business logic to retrieve customer balances.
final class SIMIntegrationCustomerBalanceInfoResponseService
{
public SIMIntegrationCustomerBalanceInfoResponseList getCustomersBalances(SIMIntegrationCustomerBalanceInfoRequest _request)
{
SIMIntegrationCustomerBalanceInfoResponseList response = new SIMIntegrationCustomerBalanceInfoResponseList();
List customerBalances = new List(Types::Class);
CustTable customer;
changecompany(_request.parmDataAreaId())
{
while select customer
where customer.CustGroup == _request.parmCustGroupId()
{
if (customer.phone())
{
SIMIntegrationCustomerBalanceInfoResponse customerBalanceResponse = new SIMIntegrationCustomerBalanceInfoResponse();
customerBalanceResponse.parmCustomerAccount(customer.AccountNum);
customerBalanceResponse.parmCustomerName(customer.name());
customerBalanceResponse.parmPhone(customer.phone());
customerBalanceResponse.parmBalance(customer.balanceMST());
customerBalances.addEnd(customerBalanceResponse);
}
}
response.parmCustomerBalances(customerBalances);
}
return response;
}
}
6. Create Service and Service Group
7. Microsoft Entra ID applications
To access the service externally:
8. Calling the Service
Use an HTTP client like Postman.
https://<your-env>.cloudax.dynamics.com/api/services/SIMIntegrationServiceGroup/SIMIntegrationCustomerBalanceService/getCustomersBalances
{
"Company": "USMF",
"CustomerGroup": "10"
}
9. JSON Serialization
D365FO automatically handles JSON serialization for classes decorated with [DataContract] and [DataMember].
The result will be like this:
{
"$id": "1",
"customerBalances": [
{
"$id": "2",
"CustomerAccount": "Cust1",
"CustomerName": "Cust1Name",
"Balance": 0.0,
"Phone": "+123456789"
},
{
"$id": "3",
"CustomerAccount": "Cust2",
"CustomerName": "Cust2Name",
"Balance": 399.5,
"Phone": "123456789"
}
}
Technical Consultant Microsoft Dynamics 365 Finance & Operations | Power Platform | Microsoft Certified MB-500 | PL-400
1moWell done Hatem! Great explanation 👍
Microsoft Dynamics 365 F&O Technical Consultant
1moMy new go-to blog ❤️