Sending Flat Files from Dynamics 365 for Operations to a Different Location

By Bill Thompson | February 28, 2017

One of the challenges we have found with Dynamics 365 for Operations is the export of flat files. Recently we had to get data (as a flat file) out of Dynamics 365 for Operations and place it in a location for a separate system to process. The process had to be secure.

Initially, we were going to use the .NET Framework functionality for FTP-ing the data to an FTP site, but found that out of the box .NET does not provide the secure FTP functionality. There are many different options (some freeware, some paid). This discussion will implement a freeware version using SSH.NET (https://github.com/sshnet/SSH.NET).

The first step is to build the dll. Once built, a reference needs to be added to the Visual Studio project. One issue we found is that this reference needs to be in a location that will be available on all different environments (Development, UAT, and Production). We ended up copying the dll (Renci.SshNet.dll) to the AOS file structure, and placing it in the root of our Model (see screenshot below).

Flat files from Dynamics 365

This file was added to the Visual Studio project, and then added into version control. This allows the file to follow the project throughout the promotion of code.

The code below is part of a class that was created to allow the batching of the file upload process (which is called AFTER the file has been created and validated to exist). The code logs into the FTP site, and once successful uploads the file to the defined location.

All of the configuration information is stored in a custom table called SysFTPSiteInfo.

Below is the code for the ftp method used. Error trapping is NOT implemented in this demonstration code.

/// <summary>
    /// This method implements sftp functionality
    /// </summary>
    /// <remarks>
    /// </remarks>
    public void ftpFile()
    {
        str ftpAddress;
        str ftpLocation;
        str ftpUser;
        str ftpPW;

        SysFTPSiteInfo ftpInfo;

        System.Object ftpo;
        System.Object ftpResponse;
        System.Net.FtpWebRequest request;
        System.IO.StreamReader reader;
        System.IO.Stream requestStream;
        System.Byte[] bytes;
    
        System.Text.Encoding utf8;
        System.Net.FtpWebResponse response;
        System.Object credential;
        
        Filename        fileType,fileNameString;
        FileName        ftpFileName,fileName;

        new InteropPermission(InteropKind::ClrInterop).assert();

        IntFilePathTable pathFile;
        
        // find the location where to save the file
        select firstonly pathFile;
        filePath = pathFile.FilePath;

        // get the ftp site info
        select firstonly ftpInfo;
        ftpAddress = ftpInfo.FTPSite;
        ftpLocation = ftpInfo.FTPFolder;
        ftpUser = ftpInfo.FTPUserId;

        < CODE REMOVED FOR READABILITY>

        // decrypt the password 
        ftpPW = cryptography.decrypt(ftpInfo.FTPPassword);        

        fileName localfileName = filePath + @'\' + expFileName;

        [filepath, filename, fileType] = fileNameSplit(localfileName);
        fileNameString= expFileName;
        ftpFileName = ftpAddress + '/' + ftpLocation + '/' + fileNameString;

        reader = new System.IO.StreamReader(localfileName);
        utf8 = System.Text.Encoding::get_UTF8();
        bytes = utf8.GetBytes( reader.ReadToEnd() );
        reader.Close();

        // secure file transfer via SFTP
        using (var sftp = new Renci.SshNet.SftpClient(ftpAddress,ftpUser,ftpPW))
        {
            sftp.Connect();
            sftp.ChangeDirectory(@"/" + ftpLocation);

            using (var fileStream = new System.IO.FileStream(localfileName, System.IO.FileMode::Open))
            {
                sftp.BufferSize = 4 * 1024;
                sftp.UploadFile(fileStream,expFileName,true,null);
            }

        }
}

Under the terms of this license, you are authorized to share and redistribute the content across various mediums, subject to adherence to the specified conditions: you must provide proper attribution to Stoneridge as the original creator in a manner that does not imply their endorsement of your use, the material is to be utilized solely for non-commercial purposes, and alterations, modifications, or derivative works based on the original material are strictly prohibited.

Responsibility rests with the licensee to ensure that their use of the material does not violate any other rights.

Start the Conversation

It’s our mission to help clients win. We’d love to talk to you about the right business solutions to help you achieve your goals.

Subscribe To Our Blog

Sign up to get periodic updates on the latest posts.

Thank you for subscribing!