Struggling with Data Export from Microsoft Dynamics 365 CRM to External Portals

Total: 1 Average: 4

Though Microsoft Dynamics 365 does not offer any built-in feature to export the CRM data to external portals so far, there is a simple way to reach there. If we create a web API as an intermediate service using Azure Cloud Services, it can easily export the data to external portals via FTP.

The process of configuring the Cloud Service and Storage in order to export CRM data to an external portal is described below.

Solution Architecture

Technical Execution of entire configuration is described in three steps:

  1. Create Storage Account (Classic) in Portal
  2. Create Cloud Service in Portal
  3. Enable the Azure Services from the CRM Plugin

1. Create Storage Account (Classic) in Portal

  • Use the URL https://portal.azure.com and search for ‘storage’ in the search panel. Select the Storage accounts (classic) from the displayed search results.
  • Once you are navigated to ‘Storage accounts’ dashboard, click ‘Add’ in order to create a new storage account.
  • Either key in or select from drop-down options the relevant details for to each field.
    • Name
    • Deployment Model: Classic – Must be classic
    • Account kind: General purpose
    • Performance: Standard
    • Replication: Keep Default
    • Subscription: Usage-Based

2. Create Cloud Service in Portal

    • Visit https://portal.azure.com and opt for Cloud services (classic).
    • Either key in or select from drop-down options the relevant details for to each field.
      • DNS Name
      • Subscription: Usage-Based
      • Resource group: Select the resource group
      • Packages
        • Deployment Label: Key in deployment label
        • Storage Account: Select previously created account
        • Upload package and configuration
          • Packages will be given with the solution
        • Environment: Production

Once you have created the Storage account and Cloud services in the portal, you are ready to move ahead.

3. Integrate the Azure Services from the CRM Plugin

I have followed the underneath high-level structure to enable the Azure Services from the CRM Plugin.

Services
       CreateTextFile(FTPFile file)
       CreateImageFile(FTPFile file)
Objects
FTPFile      
		FileName 
		PathToCreate         
		Data 
		FTPConfiguration 
		ForceCreate 
		 
		//For Image Process
		Type
		ImageResizeHeight
		ImageResizeWidth       
		AllowsResize
	  
		
FTPConfiguration
		ServerAddress        
		Username        
		Password
		PortalId

Code Citation

Models

namespace MyProject.AzureCloudService.Models
{

  [DataContract]
    public class FTPConfiguration
    {
        [DataMember]
        public string ServerAddress { get; set; }
        [DataMember]
        public string Username { get; set; }
        [DataMember]
        public string Password { get; set; }
        //[DataMember]
        //public string AgencyId { get; set; }
    }


    [DataContract]
    public class FTPFile
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Path { get; set; }
        [DataMember]
        public string Data { get; set; }
        [DataMember]
        public FTPConfiguration FTPConfiguration { get; set; }

        public bool ForceCreate { get; set; }


        //Image Process
        [DataMember]
        public string Type { get; set; }
        [DataMember]
        public int ImageResizeHeight { get; set; }
        [DataMember]
        public int ImageResizeWidth { get; set; }
        [DataMember]
        public bool AllowsResize { get; set; }
    }

    public class MyProjectResponse<T>
    {
      
        public int ResponseCode { get; set; }
      
        public string ErrorMessage { get; set; }
      
        public T Data { get; set; }

       
        public static MyProjectResponse<T> GetSuccessResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.OK
            };

            return oResponse;
        }

      
        public static MyProjectResponse<T> GetNoDataFoundResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.NoContent
            };

            return oResponse;
        }

        
        public static MyProjectResponse<T> GetInternalServerErrorResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.InternalServerError
            };

            return oResponse;
        }

        
        public static MyProjectResponse<T> GetBadRequestResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.BadRequest
            };

            return oResponse;
        }

   
        public static MyProjectResponse<T> GetDataAlreadyExistsResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.Conflict
            };
            return oResponse;
        }

      
        public static MyProjectResponse<T> GetUnauthorizedResponse()
        {
            MyProjectResponse<T> oResponse = new MyProjectResponse<T>()
            {
                Data = default(T),
                ResponseCode = (int)HttpStatusCode.Unauthorized
            };
            return oResponse;
        }
    }
}

Create Text File Function

#region Function : CreateTextFile (1)
        [HttpPost]
        [Route("api/ftpintegration/createtextfile")]
        public MyProjectResponse<string> CreateTextFile(FTPFile ftpFileCreate)
        {
            MyProjectResponse<string> response;
            FtpWebResponse ftpResponse = null;
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpFileCreate.FTPConfiguration.ServerAddress + ftpFileCreate.Path + ftpFileCreate.Name);
                request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);
                request.Method = WebRequestMethods.Ftp.UploadFile;

                request.Credentials = new NetworkCredential(ftpFileCreate.FTPConfiguration.Username, ftpFileCreate.FTPConfiguration.Password);

                //To manage forcefully creation of the file
                if (ftpFileCreate.ForceCreate == false)
                {
                    MyProjectResponse<string> readFileResponse = GetTextFileData(ftpFileCreate);
                    if (readFileResponse.ResponseCode == (int)HttpStatusCode.OK)
                    {
                        readFileResponse.Data = readFileResponse.Data.Replace("\r\nEOF\r\n", "");
                        readFileResponse.Data = readFileResponse.Data.Replace("EOF\r\n", "");
                        readFileResponse.Data = readFileResponse.Data.Replace("\r\nEOF", "");
                        readFileResponse.Data = readFileResponse.Data.Replace("EOF", "");

                        ftpFileCreate.Data = readFileResponse.Data + ftpFileCreate.Data;
                    }
                }


                byte[] fileContents = Encoding.UTF8.GetBytes(ftpFileCreate.Data);
                request.KeepAlive = false;
                request.UseBinary = true;
                request.UsePassive = true;

                request.ContentLength = fileContents.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(fileContents, 0, fileContents.Length);
                requestStream.Close();
                ftpResponse = (FtpWebResponse)request.GetResponse();

                ftpResponse.Close();
                response = MyProjectResponse<string>.GetSuccessResponse();
                response.Data = ftpResponse.StatusDescription + "\nFile Created Successfully.";
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
                response = MyProjectResponse<string>.GetInternalServerErrorResponse();
                response.ErrorMessage = ex.Message.ToString();
            }
            finally
            {
                if (ftpResponse != null)
                {
                    ftpResponse.Close();
                }
            }
            return response;
        }
        #endregion

Create Image File Function

#region Function : CreateImageFile (1)
        [HttpPost]
        [Route("api/ftpintegration/createimagefile")]
        public MyProjectResponse<string> CreateImageFile(FTPFile ftpFileCreate)
        {
            MyProjectResponse<string> response;
            FtpWebResponse ftpResponse = null;
            try
            {

                // Image Process
                WebRequest azureRequest = WebRequest.Create(ftpFileCreate.Data);
                WebResponse azureResponse = azureRequest.GetResponse();
                //  Stream stream = response.GetResponseStream();
                MemoryStream memoryStream = new MemoryStream();
                byte[] buffer = new byte[0x1000];
                using (Stream responseStream = azureResponse.GetResponseStream())
                {

                    int bytes;
                    while ((bytes = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        memoryStream.Write(buffer, 0, bytes);
                    }
                    buffer = memoryStream.GetBuffer();
                }


                if (ftpFileCreate.AllowsResize)
                {
                    Image img = Image.FromStream(memoryStream);
                    Image resized = ResizeImage(img, new Size(ftpFileCreate.ImageResizeWidth, ftpFileCreate.ImageResizeHeight));
                    MemoryStream memStream = new MemoryStream();
                    resized.Save(memStream, ImageFormat.Png);
                    buffer = memStream.GetBuffer();
                }

                // Image Process
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpFileCreate.FTPConfiguration.ServerAddress + ftpFileCreate.Path + ftpFileCreate.Name);
                request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);
                request.Method = WebRequestMethods.Ftp.UploadFile;
                request.Credentials = new NetworkCredential(ftpFileCreate.FTPConfiguration.Username, ftpFileCreate.FTPConfiguration.Password);

                request.KeepAlive = false;
                request.UseBinary = true;
                request.UsePassive = true;

                request.ContentLength = buffer.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(buffer, 0, buffer.Length);
                requestStream.Close();
                ftpResponse = (FtpWebResponse)request.GetResponse();

                ftpResponse.Close();

                response = MyProjectResponse<string>.GetSuccessResponse();
                response.Data = "File Created Successfully.";
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
                response = MyProjectResponse<string>.GetInternalServerErrorResponse();
                response.ErrorMessage = ex.Message.ToString();
            }
            finally
            {
                if (ftpResponse != null)
                {
                    ftpResponse.Close();
                }
            }
            return response;
        }
        #endregion

Conclusion

In this post, I have detailed out the process of configuring the Azure Cloud Service and Storage along with a glimpse of enabling Azure Service from CRM Plugin. This configuration will enable you to export CRM data to the external portals in the desired format in a single click.

Krutesh Amin