I recently came across a query where a customer was having trouble in using the import SDK APIs to import attachment records in CRM. So I thought of writing this blog which explains the steps required to import attachment files in CRM using auto mapping feature of CRM import SDK and its APIs along with some sample code. One can also specify an import map but in this blog I’ll cover auto map feature only to keep things simple.
STEP BY STEP EXPLANATION WITH SAMPLE CODE
On a high level the steps are as follows:
Let’s go through these steps one by one with sample code.
1. Create a CSV file containing the details of attachments that you want to import.
First create an in memory csv file which contains the details of attachments that you want to import. You can also use an already created csv file and read its contents from the disk but to keep things simple I am creating it in memory. In order touse the auto mapping feature of import the first row of csv should contain the display names of the attributes from target import entity. The rows that will follow the first row will contain actual data which should be imported in those attributes of the target entity.
In the following code sample the first row contains the comma separated display names of attributes from annotation entity followed by the data which should be there in those columns. The annotation is a special case in import hence the data for “Document” columns containsthe file name instead of actual content. I’ll show in next steps where the actual content needs to be specified.
2. Create the root import record.
This is the root import record which binds the different import files which need to be imported together. You can see this record in the “Imports” navigation area in the mail application.
3. Create import file record for attachments which contains actual file contents.
Now you need to create an import file record where actual contents on the attachment are saved. This can be done using following code.
4. Create import file record which contains mapping for attachments.
Now create another import file record which contains the data that we created in step to import annotations in CRM.
5. Call actual import SDK APIs
Once all record are in place we are ready to actually do the import work. Import SDK provides the Parse, transform and Import SDK APIs for this work. Note that these APIs submits asynchronous jobs to do the actual import work.
The unique id of asynchronous job is returned by these APIs. You can monitor the status of these jobs using the ids which are returned by these APIS.
Once all three jobs are completed your data should get imported into the system. You can check it in the opening the import job record in the application.
Following code shows how these APIs can be called.
COMPLETE SAMPLE CODE
For more information, see:
Import Data in Microsoft Dynamics CRM
Data Import Entities
Sample: Import Data Using Complex Data Map
- Huma Ramawat
The sample code in above blog is in image format. Hence pasting the code here for ease of use. Please ping leave a reply if you find some error in the code.
/// Impport attachments in CRM
public void ImportAttachmentRecords()
OrganizationServiceProxy _serviceProxy; // Initialize the _serviceProxy appropriately.
// 1. Create a CSV file containing the details of attachments that you want to import.
string fileName = DateTime.UtcNow.Ticks + ".txt";
string attachmentContent = "This is the attachment content"; // Put your attachment contents here.
string attachmentData = Convert.ToBase64String(Encoding.UTF8.GetBytes(attachmentContent));
StringBuilder sb = new StringBuilder();
//Add header row
sb.AppendLine("Title, Document, File Name, Regarding");
string accountId = "04AFD3BF-16D6-E111-A43C-00155D187A0A"; // This is the unique id of CRM record e.g. account with which you want to attach this note.
string dataRow = "attachment1, " + fileName + ", " + fileName + "," + accountId;
string csvData = sb.ToString();
// 2. Create the root import record
Import import = new Import()
ModeCode = new OptionSetValue((int)ImportModeCode.Create),
Name = "Importing data"
Guid importId = _serviceProxy.Create(import);
// 3. Create import file record for attachments which contains actual file contents.
ImportFile importAttachmentFile = new ImportFile()
Content = attachmentData, // Read contents from disk.
Name = fileName,
UseSystemMap = true,
ImportId = new EntityReference(Import.EntityLogicalName, importId),
FileTypeCode = new OptionSetValue(2)
Guid importAttachmentFileId = _serviceProxy.Create(importAttachmentFile);
// 4. Create import file record which contains mapping for attachments.
ImportFile importFile = new ImportFile()
Content = csvData, // Read contents from disk.
Name = "Attachment Import File",
IsFirstRowHeader = true,
Source = "Import Attachment",
SourceEntityName = "attachment",
TargetEntityName = Annotation.EntityLogicalName,
EnableDuplicateDetection = false,
Guid importFileId = _serviceProxy.Create(importFile);
// 5. Call import SDK APIs
// Parse the import file.
ParseImportRequest parseImportRequest = new ParseImportRequest()
ImportId = importId
ParseImportResponse parseImportResponse =
// Transform the import
TransformImportRequest transformImportRequest = new TransformImportRequest()
TransformImportResponse transformImportResponse =
// Upload the records.
ImportRecordsImportRequest importRequest = new ImportRecordsImportRequest()
ImportRecordsImportResponse importResponse =
/// Waits for the async job to complete.
/// <param name="asyncJobId"></param>
public void WaitForAsyncJobCompletion(OrganizationServiceProxy serviceProxy, Guid asyncJobId)
ColumnSet cs = new ColumnSet("statecode", "statuscode");
AsyncOperation asyncjob =
(AsyncOperation)serviceProxy.Retrieve("asyncoperation", asyncJobId, cs);
int retryCount = 100;
while (asyncjob.StateCode.Value != AsyncOperationState.Completed && retryCount > 0)
asyncjob = (AsyncOperation)serviceProxy.Retrieve("asyncoperation", asyncJobId, cs);