A few months back Microsoft announced the deprecation of the WindowsAzure.Storage and the Microsoft.Azure.Storage libraries in favor of the newer Azure.Storage.Blobs library for Dynamics 365 for Finance and Operations. These libraries are used for file based integration, when you bring in or send out data, to or from D365F&O, using text files. I have an ISV called Ariene that depends on these libraries. Many D365F&O developers are going to hit this problem at some point in the future, their code will not compile. Since Microsoft hasn't been very clear about how to proceed, I decided to write this small piece.
The original post by Microsoft can be found here. The change was originally slated to take place in 10.0.44, with the transition starting in 10.0.43. As of version 10.0.44 the older code was supposed to be phased out and no longer work. Digging around, I found out that 10.0.43, which was supposed to support older and newer libraries, doesn't yet support Azure.Storage.Blobs because it's missing a critical dll: System.Memory.Data. I tried to tweak 10.0.43 to work and lost a considerable amount of time in the process. Frustrated, I tried 10.044 and found that it contains the System.Memory.Data dll.
10.0.44 has its nuances with Azure.Storage.Blobs, I found that you can compile the new code but when you try to debug it, you'll get an error:
"The primary reference "Azure.Core, Version=1.44.1.0, Culture=neutral, PublicKeyToken=92742159e12e44c8" could not be resolved because it has an indirect dependency on the assembly "System.Memory.Data, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" which was built against the ".NETFramework,Version=v4.6.1" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.6"."
To fix this I downloaded the .NET 4.6.1 developer pack from Microsoft and installed it on my developer VM. Then I opened the .rnrproj file and changed the TargetFrameworkVersion from v4.6 to v4.6.1, and now I can hit Debug -> Start Debugging in Visual Studio and it will hit my breakpoints.
I've created this little snippet of code using the new Azure.Storage.Blobs library and as you can see, it's pretty similar to the old code:
Azure.Storage.Blobs.BlobServiceClient blobServiceClient; Azure.Storage.Blobs.BlobContainerClient blobContainerClient; Azure.Storage.Blobs.BlobClient blobClient; System.Byte[] byteArray; System.IO.MemoryStream stream; System.IO.MemoryStream downloadStream; str downloadContents; //Use your connection string, example: 'DefaultEndpointsProtocol=https;AccountName=<your account name>;AccountKey=<your account key>;EndpointSuffix=core.windows.net' blobServiceClient = new Azure.Storage.Blobs.BlobServiceClient('<your connection string>'); //Use your container name blobContainerClient = blobServiceClient.GetBlobContainerClient('<your container name>'); //Upload a file byteArray = System.Text.Encoding::UTF8.GetBytes('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'); stream = new System.IO.MemoryStream(byteArray); stream.Position = 0; blobClient = blobContainerClient.GetBlobClient('\LoremIpsum.txt'); blobClient.Upload(stream, null, System.Threading.CancellationToken::None); //Download the file downloadStream = new System.IO.MemoryStream(); blobClient = blobContainerClient.GetBlobClient('\LoremIpsum.txt'); blobClient.DownloadTo(downloadStream); downloadStream.Position = 0; using (System.IO.StreamReader reader = new System.IO.StreamReader(downloadStream, System.Text.Encoding::UTF8)) { downloadContents = reader.ReadToEnd(); } info(downloadContents); //Delete the file blobClient = blobContainerClient.GetBlobClient('\LoremIpsum.txt'); blobClient.Delete(0, null, System.Threading.CancellationToken::None);
And for those of you that are using Azure files instead of blobs, you can use this as a reference for your code migration to Azure.Storage.Files.Shares:
Azure.Storage.Files.Shares.ShareServiceClient shareServiceClient; Azure.Storage.Files.Shares.ShareClient shareClient; Azure.Storage.Files.Shares.ShareDirectoryClient shareDirectoryClient; Azure.Storage.Files.Shares.ShareFileClient shareFileClient; Azure.Storage.Files.Shares.Models.ShareFileDownloadInfo downloadInfo; System.Byte[] byteArray; System.IO.MemoryStream stream; System.IO.MemoryStream downloadStream; str downloadContents; //Use your connection string, example: 'DefaultEndpointsProtocol=https;AccountName=<your account name>;AccountKey=<your account key>;EndpointSuffix=core.windows.net' shareServiceClient = new Azure.Storage.Files.Shares.ShareServiceClient('<your connection string>'); //File Share name shareClient = shareServiceClient.GetShareClient('<your file share name>'); shareDirectoryClient = shareClient.GetRootDirectoryClient(); //Upload a file byteArray = System.Text.Encoding::UTF8.GetBytes('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'); stream = new System.IO.MemoryStream(byteArray); stream.Position = 0; stream.Position = 0; shareFileClient = shareDirectoryClient.GetFileClient('LoremIpsum.txt'); int64 fileSize = 10 * byteArray.Length; shareFileClient.Create(fileSize, null, null, null, null, null, System.Threading.CancellationToken::None); shareFileClient.Upload(stream, null, System.Threading.CancellationToken::None); //Download file downloadStream = new System.IO.MemoryStream(); shareFileClient = shareDirectoryClient.GetFileClient('LoremIpsum.txt'); downloadInfo = shareFileClient.Download(null, System.Threading.CancellationToken::None); System.IO.Stream content = downloadInfo.Content; content.CopyTo(downloadStream); downloadStream.Position = 0; using (System.IO.StreamReader reader = new System.IO.StreamReader(downloadStream, System.Text.Encoding::UTF8)) { downloadContents = reader.ReadToEnd(); } info(downloadContents); //Delete the file shareFileClient = shareDirectoryClient.GetFileClient('LoremIpsum.txt'); shareFileClient.Delete(null, System.Threading.CancellationToken::None);