My requirement was to register a plugin so that every time a file is attached to some entities, I download the file to a temp folder for performing some processing. Actually, in my case it was processing an Excel file as a more user-friendly data input for line items in opportunities and quotes, but that is anecdotic.

The 3 key points I would like to share here with you is how to:

  • Retrieve the note (annotation entity which is the one who stores the file)
  • Retrieve the file content
  • Save the file to a location in the web server

Below are some parts of my plugin .cs file:



protected void ExecutePostNoteCreate(LocalPluginContext localContext)
    string tempFile = string.Empty;
    IPluginExecutionContext context = localContext.PluginExecutionContext;
    IOrganizationService organizationService = localContext.OrganizationService;         
    if (context.InputParameters.Contains("Target") &&
        context.InputParameters["Target"] is Entity)
        Entity noteEntity = (Entity)context.InputParameters["Target"];
        Annotation note = noteEntity.ToEntity<Annotation>();


// RETRIEVE THE FILE CONTENT (DocumentBody property)

if (!string.IsNullOrEmpty(note.FileName))
   tempFile = SaveFile(note.FileName, note.DocumentBody);



private static string SaveFile(string fileName, string noteBody)
    string outputFileName = @"C:\temp\" + fileName;
    if (!string.IsNullOrEmpty(noteBody))
        // Download the attachment in the current execution folder.
        byte[] fileContent = Convert.FromBase64String(noteBody);
        System.IO.File.WriteAllBytes(outputFileName, fileContent);
        throw new InvalidPluginExecutionException("File content is empty or cannot be retrieved");
    return outputFileName;

Take note I’m using System.IO.File.WriteAllBytes. This is what did work for me. I’ve tried using WriteAllText and also FileStream but when trying to open the generated file, it was not in the right format.


Hope it helps,

PP [twitter: @pabloperalta]