When, Why, and How to Use Data Contracts in Dynamics 365
A common problem we encounter in Microsoft Dynamics 365 development is how to pass data between functions and services. In this post we will review strategies that balance the needs of strongly typed data without introducing technical debt. We’ll explore how we can write our solution today which supports extension tomorrow.
One Big Method
Let us examine a method that asks for a lot of data and returns very little. Imagine a business requirement to process quantity updates for sales lines. We could write our business logic, exposing individual arguments.
public boolean processQtyUpdate(InventTransId _inventTransId,
InventQty _origQty,
InventQty _newQty,
boolean _showError = false)
{
boolean ok = true;
//Do work that solves today's problem
return ok;
}
This approach enforces exchange of strongly typed data but limits our ability to extend this function to meet future business needs. Since chain of command/event subscriptions cannot change the method signature, individually defined arguments are set in stone until the next platform update.
Making a Request
We should approach the problem by submitting a request contract instead of individual arguments.
public boolean processQtyUpdateBetter(SalesLineQtyUpdateRequestContract _request)
{
boolean ok = true;
SalesLine salesLine = SalesLine::findInventTransId(_request.InventTransId());
//Do work that solves today's problem and enables new requirements
return ok;
}
This approach, coupled with an extensible pattern of hydrating the request contract, allows extensions to add new data input to our processor method. The method signature does not need to change to support future business requirements. The input data is strongly typed and easy to read in the debugger.
Writing a Data Contract
Data contacts are easy to create. They are classes with protected (by default) global variables exposed through public get/set (parm) methods. When using data contracts with SysOp or reporting, the class should be decorated with DataContractAttribute, and each parm method should be decorated with DataMemberAttribute.
[DataContract()]
class SalesLineQtyUpdateRequestContract
{
InventTransId inventTransId;
[DataMember()]
public InventTransId InventTransId(InventTransId _inventTransId = inventTransId)
{
inventTransId = _inventTransId;
return inventTransId;
}
}
Returning a Response
Data contracts are also our preferred approach to return multiple pieces of data to the caller (instead of a container of data).
public SalesLineQtyUpdateResponseContract
processQtyUpdateUltimate(SalesLineQtyUpdateRequestContract _request)
{
SalesLineQtyUpdateResponseContract response = new SalesLineQtyUpdateResponseContract();
SalesLine salesLine = SalesLine::findInventTransId(_request.InventTransId());
try
{
//Do work that solves today's problem and enables new requirements
}
catch
{
response.Fault(true);
}
return response;
}
Arguments Against Containers
One could argue accepting and returning a container would achieve the same ends. Though true, we discourage this anti-pattern. The container does not ensure strongly typed contents. The extension story for containers requires unknown parties to play well with each other and requires unnecessary amounts of data validation when extracting the data from the container index. Containers are harder to read when debugging. Utilizing a container to pass our request and response data will only shift technical debt from the “cannot extend” to “where’s my notes on how to parse this return.”
In this blog, we have shown that by utilizing data contracts, the groundwork is laid to meet future business requirements via extension. Additionally, contracts allow handshake agreement on variables between callers and support developer productivity by being easier to read and extend.


Hidden Treasures of Advanced Warehousing
Make the most of Microsoft Dynamics 365’s Advanced Warehousing module and gain insight into the hidden treasures to unlock value.
Deep Expertise in Dynamics AX and D365 Development
enVista is dedicated to helping the Microsoft community by continuously sharing our in-depth knowledge of X++ and Microsoft Dynamics 365 development. If you are struggling with Dynamics AX or D365 development, contact us, and we will connect you with one of our in-house experts.
Read our other topics in our D365 Developer Series: