Integration Options in Dynamics 365 Finance & Operations
Question 51 — OData, custom services, Business Events, recurring integrations and dual-write.
Interview Question
Model Answer (Short)
D365 F&O offers several integration patterns depending on volume, direction and timing. OData is a RESTful protocol for real-time, record-by-record CRUD against public data entities. Custom services (SOAP/JSON) expose your own X++ logic as an API for synchronous request/response operations. Business Events push outbound notifications to endpoints (Event Grid, Service Bus, Power Automate) when a business action occurs — ideal for event-driven integrations. Recurring integrations build on DMF data projects to exchange files on a schedule for medium/large batches. Dual-write provides near-real-time, bi-directional sync between F&O and Dataverse for shared master data. The right choice balances latency, payload size and coupling.
The Integration Options
OData
- RESTful protocol for real-time CRUD on public data entities.
- Best for low-volume, synchronous integrations and queries.
- Supports query options (
$filter,$select,$expand).
Custom services
- Expose your own X++ business logic as SOAP/JSON endpoints.
- Best for synchronous request/response operations with custom contracts.
- Built with a service, service group and data contract.
Business Events
- Outbound, event-driven notifications when a business action occurs.
- Endpoints include Azure Event Grid, Service Bus, and Power Automate.
- Best for reacting to events without polling.
Recurring integrations & dual-write
- Recurring integrations exchange files on a schedule using DMF data projects.
- Best for medium/large batch file-based exchange with external systems.
- Dual-write gives near-real-time bi-directional sync with Dataverse.
- Best for shared master data across F&O and the Power Platform / CE apps.
Prerequisites (Rule 5)
- Visual Studio with the Dynamics 365 developer tools.
- A custom model / package for services/entities.
- An Azure AD app registration for authenticating external callers.
- For Business Events: a configured endpoint (Event Grid / Service Bus).
Code Example — A custom service contract & operation
// Data contract
[DataContractAttribute]
class AbcCreateCustomerRequest
{
CustAccount custAccount;
Name name;
[DataMemberAttribute('CustAccount')]
public CustAccount parmCustAccount(CustAccount _v = custAccount)
{ custAccount = _v; return custAccount; }
[DataMemberAttribute('Name')]
public Name parmName(Name _v = name)
{ name = _v; return name; }
}
// Service class exposing the operation
class AbcCustomerService extends SysOperationServiceBase
{
public AbcCreateCustomerResponse createCustomer(AbcCreateCustomerRequest _req)
{
// ... create the customer using _req ...
AbcCreateCustomerResponse response = new AbcCreateCustomerResponse();
return response;
}
}
Defining a Business Event
// A business event carries a payload raised when something happens
class AbcOrderApprovedBusinessEvent extends BusinessEventsBase
{
private AbcOrderApprovedContract contract;
public static AbcOrderApprovedBusinessEvent newFromOrder(SalesTable _salesTable)
{
AbcOrderApprovedBusinessEvent be = new AbcOrderApprovedBusinessEvent();
be.contract = AbcOrderApprovedContract::newFromOrder(_salesTable);
return be;
}
[Wrappable(true), Replaceable(true)]
public BusinessEventsContract buildContract()
{
return contract;
}
}
Consuming an entity via OData (conceptual)
# Public entity "Customers" exposed via OData
GET https:///data/Customers?$filter=CustomerGroupId eq 'DOM'&$select=CustomerAccount,Name
POST https:///data/Customers # single-record create
Integration Options Compared
| Option | Direction | Timing | Best for |
|---|---|---|---|
| OData | Inbound & outbound CRUD | Real-time | Low-volume live integration |
| Custom service | Request/response | Real-time (sync) | Custom X++ logic as an API |
| Business Events | Outbound | Near real-time | Event-driven notifications |
| Recurring integration | Inbound & outbound files | Scheduled batch | Medium/large file exchange |
| Dual-write | Bi-directional | Near real-time | Shared master data w/ Dataverse |
Points the interviewer wants to hear
- OData = real-time CRUD on public entities; custom services = custom X++ APIs.
- Business Events = outbound, event-driven notifications.
- Recurring integrations = scheduled, file-based DMF exchange.
- Dual-write = near-real-time bi-directional sync with Dataverse.
- Choose by volume, direction and timing.
Likely Follow-up Questions
- When would you use a custom service instead of OData?
- How do Business Events differ from polling an entity?
- What underlies recurring integrations?
- What is dual-write and when is it the right choice?
Key Takeaway
Match the integration to the need: OData for live CRUD, custom services for bespoke logic, Business Events for event-driven pushes, recurring integrations for scheduled file batches, and dual-write for bi-directional Dataverse sync — always weighing volume, direction and timing.