web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

D365FO and .net dll

(3) ShareShare
ReportReport
Posted on by 107
Hello, I am trying to create a helper class in x++ that will upload files to Azure blob storage.
 
First I used Microsoft.WindowsAzure.Storage dll and it worked fine. But then I found that this package has been deprecated https://www.nuget.org/packages/microsoft.azure.storage.blob/ so I tried to rewrite the code using the recomended package Azure.Storage.Blobs.
Both Microsoft.WindowsAzure.Storage and Azure.Storage.Blobs are included in AosService\PackagesLocalDirectory\bin so we can reference them diractly in x++ code.
 
The problem is that containerClient.CreateIfNotExists() from Azure.Storage.Blobs does not compile and throwing bunch of errors
 
Azure.Storage.Blobs Code (throws errors on the first lines):
 public static void uploadBlob(System.IO.MemoryStream file, str fileName, str connectionString, str containerName, int expireMinutes = 5)
 {
     // Create a BlobServiceClient using the connection string
     Azure.Storage.Blobs.BlobServiceClient blobServiceClient = new Azure.Storage.Blobs.BlobServiceClient(connectionString);
     
     // Get a reference to the container
     Azure.Storage.Blobs.BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient("ponta");
     
     // Create the container if it doesn't exist
     containerClient.CreateIfNotExists(); 
     
     ...
 
}
 
Errors:
Severity    Code    Description    Project    File    Line    Suppression State
Error        The "BuildTask" task returned false but did not log an error.    ExportInvoice (ISV) [ISAIS]    C:\Program Files (x86)\MSBuild\Microsoft\Dynamics\AX\Microsoft.Dynamics.Framework.Tools.BuildTasks.17.0.targets    63    
Error        Cannot convert the default value of the 'IDictionary`2' parameter of method 'CreateIfNotExists' on CLR type 'Azure.Storage.Blobs.BlobContainerClient' because it cannot be converted to a valid X++ literal. Pass a literal value for 'IDictionary`2' instead.    ExportInvoice (ISV) [ISAIS]    K:\AosService\PackagesLocalDirectory\bin\XppSource\ISAIS\AxClass_ISAIS_AzureStorageAccountHelper.xpp    17    
Error        Cannot convert the default value of the 'CancellationToken' parameter of method 'CreateIfNotExists' on CLR type 'Azure.Storage.Blobs.BlobContainerClient' because it cannot be converted to a valid X++ literal. Pass a literal value for 'CancellationToken' instead.    ExportInvoice (ISV) [ISAIS]    K:\AosService\PackagesLocalDirectory\bin\XppSource\ISAIS\AxClass_ISAIS_AzureStorageAccountHelper.xpp    17    
Error        Cannot convert the default value of the 'BlobContainerEncryptionScopeOptions' parameter of method 'CreateIfNotExists' on CLR type 'Azure.Storage.Blobs.BlobContainerClient' because it cannot be converted to a valid X++ literal. Pass a literal value for 'BlobContainerEncryptionScopeOptions' instead.    ExportInvoice (ISV) [ISAIS]    K:\AosService\PackagesLocalDirectory\bin\XppSource\ISAIS\AxClass_ISAIS_AzureStorageAccountHelper.xpp    17    

I now started to wonder is worth it to write this kind of logic in x++ or just write it in .net and reference it in x++.
What do you think, what are Pros and Cons?
 
 
 
 
 
 
Categories:
I have the same question (0)
  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at
    Regarding "Cannot convert the default value of the 'CancellationToken' parameter of method 'CreateIfNotExists' on CLR type 'Azure.Storage.Blobs.BlobContainerClient' because it cannot be converted to a valid X++ literal. Pass a literal value for 'CancellationToken' instead.", the message already contains a suggested solution. Have you tried it?
  • Suggested answer
    Anton Venter Profile Picture
    20,346 Super User 2025 Season 2 on at
    Looking at the stack trace, there is a clue there. Have you tried to pass the default value instead of leaving it empty?

    "...Pass a literal value for 'BlobContainerEncryptionScopeOptions' instead...."
     
    As far as the pros and cons go, with these kiund of things, I always to try to do as much as possible in X++. This reduces dependencies.
  • tdgscorpion Profile Picture
    107 on at
    I already tried create these objects

    Azure.Storage.Blobs.Models.PublicAccessType publicAccessType = Azure.Storage.Blobs.Models.PublicAccessType::None;
     
    and 
     
    Azure.Storage.Blobs.Models.BlobContainerEncryptionScopeOptions encryptionScopeOptions = null;
     
    are fine but could not create 

    System.Collections.Generic.IDictionary`2 metadata
     
    and 
     
    System.Threading.CancellationToken cancellationToken
     
    these types throw errors
    System.Collections.Generic.IDictionary`2 is sintactical, I don`t know what is this `2
    and CancellationToken is not found in System.Threading

     
  • CU07020437-0 Profile Picture
    2 on at
    Hello, where you able to fix this error? Please let me know if you did. 
  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at
    System.Collections.Generic.IDictionary`2 is a generic collection; you can't write it like that. X++ doesn't support generics, therefore if you want to do things like declare generic types, you'll be better off writing a C# library (and calling this library from X++) then trying to do it directly in X++. There is a good chance that it'll solve the original problem as well; just make sure that your C# library uses the same assembly versions as F&O.
  • Suggested answer
    Gerhard Rieser Profile Picture
    6 on at
    Hello,
    for me following code works:
     
    BlobContainerClient blobContainer = blobServiceClient.GetBlobContainerClient(_blobContainerName);
    Azure.Storage.Blobs.Models.PublicAccessType publicAccessType = Azure.Storage.Blobs.Models.PublicAccessType::None;
    Azure.Storage.Blobs.Models.BlobContainerEncryptionScopeOptions encryptionScopeOptions = null;
    System.Threading.CancellationToken cancelationToken = new System.Threading.CancellationToken();
    blobContainer.CreateIfNotExists(publicAccessType, null,encryptionScopeOptions,cancelationToken);


    It creates the blob if it does not exist.
  • WV-08081158-0 Profile Picture
    7 on at
    Hi, were you able to solve this?

    I do have exact same problem, the compiler fails on the character between Dictionary and 2 when declaring from X++.
    IDictionary`2
     
    I did try:
           System.Collections.Generic.IDictionary`2<System.String, System.String> metadata =
             new System.Collections.Generic.IDictionary`2<System.String, System.String>();
     
            var metadata = new System.Collections.Generic.IDictionary`2<System.String, System.String>();
     
    Both times it fails on the ` character before the 2.
     
    I'll also try the solution by Gerhard, just passing null for the IDictionary`2 , compiler seems to like that.

    That does indeed work, thanks Gerhard. Also when using AFS instead of Blob.
  • tdgscorpion Profile Picture
    107 on at
    Tnak you all for the responses. I wrote all the logic in C# library and used it in X++
  • Verified answer
    Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at
    @WV-08081158-0 Please create a new thread for your question, because this one was about a problem CreateIfNotExists(). In short, your code indeed isn't valid X++ and will never compile. You should either avoid generic types in X++ (typically by doing so in a C# library), you'll need to instantiate the object via reflection or you can try the limited (and not really supported) capability for generic types in X++ using the C# syntax (<>).
  • WV-08081158-0 Profile Picture
    7 on at
     
    as I did explain in my post. I was able to solve it the same way as Gerhard. So no question and no new thread ;-).
     
    Following code does work:
            ShareFileClient fileClient = new Azure.Storage.Files.Shares.ShareFileClient(connectionString, afsFileShareName, filePathAndName);
            ShareFileHttpHeaders httpHeaders = new Azure.Storage.Files.Shares.Models.ShareFileHttpHeaders();
            FileSmbProperties fileSmbProperties = new Azure.Storage.Files.Shares.Models.FileSmbProperties();
            System.String   filePermission = '';
            ShareFileRequestConditions shareFileRequestConditions = new Azure.Storage.Files.Shares.Models.ShareFileRequestConditions();
            System.Threading.CancellationToken cancellationToken = new System.Threading.CancellationToken();
            fileClient.Create(_stream.Length, httpHeaders, null, fileSmbProperties, filePermission, shareFileRequestConditions, cancellationToken);
           
            ShareFileUploadOptions shareFileUploadOptions = new Azure.Storage.Files.Shares.Models.ShareFileUploadOptions();
            fileClient.Upload(_stream, shareFileUploadOptions, cancellationToken);
           
     
    grtz
    Wim

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 551 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 450 Super User 2025 Season 2

#3
BillurSamdancioglu Profile Picture

BillurSamdancioglu 278 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans