D365 F&O cloud to on prem file transfer using Azure blob storage

  D365 F&O → Azure Blob Container → On-Prem System (file transfer)


Scenario:

Files generated in Dynamics 365 Finance & Operations (D365 F&O) are uploaded to an Azure Blob Container, and an on-premises system later downloads them using AzCopy.

Architecture Flow






X++ Code — Upload to Azure Blob Storage:

using Microsoft.WindowsAzure.Storage;

using Microsoft.WindowsAzure.Storage.Blob;

using Microsoft.Dynamics.AX.Framework.FileManagement;

using BlobStorageAssembly = Microsoft.WindowsAzure.Storage;


public class InvoiceFileOnBlobStorage

{

    public static void main(Args _args)

    {

        str connectionString = CloudStorageAccount::Parse(

            "DefaultEndpointsProtocol=https;AccountName=azureContainerAccountName;"

            "AccountKey=7sU+VCk1sb1uCnWChsvwhxvRTY93mSnvhv7b+Aw==;"

            "EndpointSuffix=core.windows.net"

        );


        BlobStorageAssembly.CloudStorageAccount storageAcct =

            BlobStorageAssembly.CloudStorageAccount::Parse(connectionString);


        BlobStorageAssembly.Blob.CloudBlobClient blobClient =

            storageAcct.CreateCloudBlobClient();


        BlobStorageAssembly.Blob.CloudBlobContainer blobContainer =

            blobClient.GetContainerReference(blobStorageParameter.ContainerName);


        blobContainer.CreateIfNotExistsAsync();


        utcDateTime now = DateTimeUtil::utcNow();

    

        str fileName = strFmt("ExportFileName_%1.csv", formattedOutput);

        str agingFileName = strFmt("AgingReport_%1_as_on.pdf", formattedOutput);


        BlobStorageAssembly.Blob.CloudBlockBlob blockBlob =

            blobContainer.GetBlockBlobReference(fileName);


        if (blockBlob && !blockBlob.Exists(null, null))

        {

            str fileContent = this.generateInvoiceFile(fileName); // Generate invoice content 


            if (fileContent)

            {

                // Upload invoice CSV

                blockBlob.UploadText(fileContent, null, null, null, null);


                // Upload aging report PDF

                BlobStorageAssembly.Blob.CloudBlockBlob blockBlob2 =

                    blobContainer.GetBlockBlobReference(agingFileName);


                System.Byte[] reportBytes = this::getSSRSByte(agingFileName);

                System.IO.MemoryStream stream = new System.IO.MemoryStream(reportBytes);


                if (stream)

                {

                    blockBlob2.UploadFromStream(stream, null, null, null);

                    info("Customer aging report uploaded successfully");

                }


                blockBlob2.FetchAttributes(null, null, null);

                blockBlob.FetchAttributes(null, null, null);


                BlobStorageAssembly.Blob.BlobProperties blobProperties = blockBlob.Properties;


                if (blobProperties.Length != 0)

                {

                    info("Invoice file uploaded successfully");

                }

            }

        }

        else

        {

            error("File already exists in blob container");

        }

    }


    public static System.Byte[] getSSRSByte(str _fileName)

    {

        SrsReportRunController controller = new SrsReportRunController();

        SRSPrintDestinationSettings settings;

        System.Byte[] reportBytes = new System.Byte[0]();

        SRSProxy srsProxy;

        System.IO.MemoryStream stream;

        SRSReportRunService srsReportRunService = new SrsReportRunService();

        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;

        Map reportParametersMap;

        SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();


        // Configure SSRS controller

        controller.parmReportName(ssrsReportStr(CustAgingReport, DesignWithNoDetailAndNoTransactionCur));

        

        // Printer settings

        settings = controller.parmReportContract().parmPrintSettings();

        settings.printMediumType(SRSPrintMediumType::File);

        settings.fileName(_fileName + ".pdf");

        settings.fileFormat(SRSReportFileFormat::PDF);


        // Prepare and render report

        controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());

        controller.parmReportContract().parmReportExecutionInfo(executionInfo);

        reportParametersMap = srsReportRunService.createParamMap(controller.parmReportContract());

        parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);


        srsProxy = SRSProxy::construct(controller.parmReportContract().parmReportServerConfig());


        // Actual rendering to byte array

        reportBytes = srsProxy.renderReportToByteArray(

            controller.parmReportContract().parmReportPath(),

            parameterValueArray,

            settings.fileFormat(),

            settings.deviceInfo()

        );


        return reportBytes;

    }

}


Next Step (On-Prem Download via AzCopy)

Once uploaded, the on-prem system can download the files using an AzCopy command or script such as:

azcopy copy "https://<storageaccount>.blob.core.windows.net/<container>?<SAS_TOKEN>" "D:\InboundFiles" -

Comments

Popular posts from this blog

Execute D365 F&O SSRS report with parameter and upload report output on Azure blob storage using X++

Microsoft D365 F&O: Remove custom models from deployable package

Generate Text/CSV/DAT file using X++ and upload on Azure blob storage