File formats
A connector delivers bytes; the processing class decides how to read them. The format is therefore independent from both the message type and the connector — the same CSV parser works whether the file arrived over SFTP, from an Azure File Share, or was uploaded by hand during testing.
| Format | Read with | Write with | Page |
|---|---|---|---|
| CSV | DEVFileReaderCSV | Bulk-export stream helpers, DEVFileWriterExcel::getCSVStream | CSV |
| Excel | DEVFileReaderExcel | DEVFileWriterExcel | Excel |
| XML | DEVIntegXMLReadHelper + System.Xml | System.Xml.XmlDocument | XML |
| JSON | DEVIntegJObject, FormJsonSerializer | DEVIntegJsonWriter, FormJsonSerializer | JSON |
| AI recognition, returns JSON | not supported — read only | PDF (AI) | |
| Standard entity files | DMF engine via DEVIntegProcessDMF | not wrapped — see the page | DMF |
DEVFileReaderCSV, DEVFileReaderExcel and DEVFileWriterExcel live in the DEVCommon model and have no dependency on the integration framework — you can use them in any RunBase dialog. The JSON and XML helpers live in DEVExternalIntegration.
Getting the payload in
An inbound message stores its payload once, and exposes it two ways:
// binary payload — files from SFTP, Azure File Share, manual upload
System.IO.MemoryStream fileStream = messageTable.getFileStream();
// text payload — Service Bus messages, REST responses
str payload = messageTable.getDataString();
A class that must work over both file and non-file connectors asks the message type which one it is:
str payload;
if (messageTable.messageTypeTable().isFileBasedConnection())
{
System.IO.MemoryStream fileStream = messageTable.getFileStream();
if (! fileStream)
{
throw error(strFmt("File %1 is empty", messageTable.Name));
}
payload = new System.IO.StreamReader(fileStream).ReadToEnd();
}
else
{
payload = messageTable.getDataString();
}
Whatever the format, the parsed values go into staging tables first, and the D365FO document is built from staging in a second step. See Inbound for why this two-step shape matters.
Getting the payload out
Outbound code builds the payload, then hands it to a base-class method that knows the transport:
| Export style | Build | Send |
|---|---|---|
| Periodic file | initCSVStream(), writeHeaderLine(), writeDataLine() | sendFileToStorage() |
| Periodic queue message | any string, usually DEVIntegJsonWriter | sendMessageToServiceBus() |
| Event-based file | a System.IO.MemoryStream you produce | sendMessageFileStorageCache() |
| Event-based queue message | a string | sendMessageServiceBusCache() |
| Event-based web call | a string | sendWebMessage() |
Choosing a format
- CSV — the default for bulk file exchange and legacy/EDI partners. Fastest to read, smallest files, but no types and no nesting.
- Excel — when a person prepares or reviews the file. Real cell types and formatting, at roughly three times the parsing cost of CSV.
- JSON — the default for queues and web APIs, and the only comfortable choice for header/lines documents.
- XML — B2B document standards (OAGIS, EDIFACT-over-XML, carrier manifests) where the schema is dictated to you.
- PDF — only when the source genuinely has no structured feed; recognition results always need validating.
- DMF — standard entities with no custom logic; best for prototyping an interface before writing the real import.