How to send CSV/Excel file from azure blob storage to DMF data project through X++

Hello all,

I have requirement that third party application will send the CSV file azure blob storage.
From azure blob I have to send this to DMF data project to import it D365 F&O.

I have followed below link but I can only see that data from blob and get the file names
but not bale to send it to D365 DMF data project

And also I followed below link where it will take file from user and and send to Data project but could not mix both links.

Please suggest if any

Use logic apps. Instead of using the dynamics 365 connector, use the HTTP connector and send to the enqueue endpoint.

here’s a link from michael stashwick’s presentation at DynamicsCon that might help.

DynamicsCon - Michael Stashwick Logic Apps and Dynamics 365

Hello Jacob,

customer is not willing to use logicapp, due to various reasons.

I have to do it through X++ and I need to send file from azure blob to DMF data project.

Please suggest if any logic or reference documentation, this is bit critical for me.

The links that I have mentioned is talking about getting file name from azure blob and I need to send that file to DMF project with X++ thats where I struck

Please help on how to do it through dynamics 365 connector

then i have no idea :slight_smile: maybe someone else has a better option.

Hi Team,

If any suggestion please suggest, this is bit critical integration .

I have requirement that third party application will send the CSV file to azure blob storage.
From azure blob I have to send this to DMF data project to import it D365 F&O with X++.

Please suggest if you have any possible solution for this

If the customer doesn’t like Logic Apps, use Azure Functions instead.
And if the customer doesn’t like Azure at all, then why we’re talking about getting data from Azure storage to a cloud ERP running in Azure too?
Deciding not to use the right tools for the job means a lot of extra work, and if don’t know how to do it in any other way, then it means not being able to do the job at all.
Anyway, if you insist, reading data though Azure Storage API is quite easy (I already showed it to you in your other thread). Injecting files to data management from X++ will likely be more difficult, because that’s not what you’re supposed to do. I don’t have code for that, but I’m pretty sure that it can be done. Instead, you should use data management APIs from outside (such as Azure Functions).

Hello Martin,

I am able to read the file names and file content with X++ and below but not able to send it to DMF

CloudBlobDirectory cloudBlobDirectory;// The directory of the blob container
container con;
cloudBlobDirectory = cloudBlobContainer.GetDirectoryReference(“SainaCloudConsulting\Test1”);//File path where the files are stored
System.Collections.IEnumerable lstEnumarable = cloudBlobDirectory.ListBlobs(false, 0, null, null);
System.Collections.IEnumerator lstEnumarator = lstEnumarable.GetEnumerator();
List filenames = new List(Types::String);
while(lstEnumarator.MoveNext())
{
IListBlobItem item = lstEnumarator.Current;
if(item is CloudBlockBlob)
{
CloudBlockBlob blob = item;
blob.FetchAttributes(null, null, null);
con = str2con(blob.name, “/”);
filenames.addStart(conPeek(con,conlen(con)));
}
}

With above code I have all file names from azure storage account.

I have below code to send the file to DMF data project from user manually by browsing

class XYZCustGroupImport
{
private static DMFDefinitionGroup findDMFDefinitionGroup()
{
DMFDefinitionGroup definitionGroup;

    select firstonly definitionGroup
        where definitionGroup.DefinitionGroupName == 'CustGroupImport'; //DMF import data project

    return definitionGroup;
}

private static DMFDefinitionGroupEntity findDMFDefinitionGroupEntity(DMFDefinitionGroup _definitionGroup)
{
    DMFDefinitionGroupEntity definitionGroupEntity;
    DMFEntity dmfEntity;

    select firstonly RecId, Entity from definitionGroupEntity exists join dmfEntity
        where definitionGroupEntity.DefinitionGroup == _definitionGroup.DefinitionGroupName
            && dmfEntity.EntityName == definitionGroupEntity.Entity
            && dmfEntity.TargetEntity == dataentityviewstr(CustCustomerGroupEntity);

    if (!definitionGroupEntity)
    {
        throw error(strFmt("@DMF:DMFNoEntityExists", _definitionGroup.DefinitionGroupName));
    }

    return definitionGroupEntity;
}

private static DMFLocalFilePath applyTransforms(SharedServiceUnitFileID _uploadedStatement, DMFDefinitionGroup definitionGroup)
{
    DMFDefinitionGroupEntity    definitionGroupEntity = XYZCustGroupImport::findDMFDefinitionGroupEntity(definitionGroup);
    DMFExecutionId              executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

    DMFDefinitionGroupExecution execution = DMFDefinitionGroupExecution::find(
        definitionGroup.DefinitionGroupName,
        definitionGroupEntity.Entity,
        executionId,
        true);

    execution.IsTransformed = NoYes::No;
    DMFLocalFilePath filePath = execution.applyTransforms(_uploadedStatement);

    DMFExecution e = DMFExecution::find(executionId, true);
    e.delete();

    return filePath;
}

public static void main(Args _args)
{      
    SharedServiceUnitFileID fileId;

    //Get the file from user
    FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;

    if (result && result.getUploadStatus())
    {
        fileId = result.getFileId();

        DMFDefinitionGroup          definitionGroup = XYZCustGroupImport::findDMFDefinitionGroup();

        XYZCustGroupImport::applyTransforms(fileId, definitionGroup);

        DMFDefinitionGroupEntity    definitionGroupEntity = XYZCustGroupImport::findDMFDefinitionGroupEntity(definitionGroup);
        DMFExecutionId              executionId = DMFUtil::setupNewExecution(definitionGroup.DefinitionGroupName);

        // Find execution
        DMFDefinitionGroupExecution execution = DMFDefinitionGroupExecution::find(definitionGroup.DefinitionGroupName, definitionGroupEntity.Entity,
                                                                                    executionId, true);
        execution.FilePath = fileId;
        execution.IsTransformed = NoYes::Yes;
        execution.update();

        // Import the file via quick import DMF
        DMFQuickImportExport::doPGImport(definitionGroup.DefinitionGroupName, executionId, true);
        
        //deletes file
        result.deleteResult();
    }
}

}

But I am not able to incorporate the code which I have, to get filenames from azure blob into the code that sending the file to DMF

I have to something with below line which will take the file from user manually
FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;

Please suggest if we can do something on it

Look at MSDyn365FO: Execution of Data projects through X++ code - it shows how to import data from a data stream.

Getting a stream from CloudBlockBlob is easy - simply call its DownloadToStream() method.