Introduction
Microsoft CRM 3.0 has the ability to store files as attachments for any entity that supports notes. This article is a guide to how an article would be attached to a note (otherwise known as an annotation within CRM 3.0).
To understand how to attach a file in CRM 3.0, you need to understand CRM's file attachment architecture. Almost all entities in the system can have notes. When manually attaching a file through the UI, a reference to the file shows up in the notes section. That is because CRM holds all file attachments that are not for activities as notes.
You will have to do the following:
- Create or retrieve the entity that you want the file to be attached to.
- Read the file steam and encode it to a Base64 string.
- Create the
UploadFromBase64DataAnnotationRequest object and execute it.
Using the code
I will first explain the steps and code required to attach a file to any entity. Let's assume you want to attach a PDF file to a client's contact record in CRM programmatically.
First, you will need the contact ID GUID of the target contact record. Secondly, you will need to create a new note. CRM attaches all files that are not activity attachments as notes.
To create a note, use the following block of code:
CrmService myCRMService = new CrmService();
myCRMService.Credentials = System.Net.CredentialCache.DefaultCredentials;
annotation note = new annotation();
note.subject = "my attachment";
note.ownerid = new Owner();
note.ownerid.type = "systemuser";
note.ownerid.Value = new Guid("000-000-0000"); <-- don't use this value
note.ownerid.name = "Administrator";
//#3
note.objectid = new Lookup();
note.objectid.name = "contact name";
note.objectid.type = EntityName.contact.ToString(); <-- use the correct type
note.objectid.Value = new Guid("000-000-0000-000"); <-- use the contact's guid
note.objecttypecode = new EntityNameReference();
note.objecttypecode.Value = EntityName.contact.ToString();
Guid newNoteID = new Guid();
newNoteID = myCRMService.Create(t);
- #1 A note entity is known in CRM as an Annotation.
- #2 Like all other user owned entities in CRM, you need to assign an owner. In this example, I used the system administrator.
- #3 The annotation class has what is known as the object ID; it is a property of type
Lookup().
You need to tell CRM where you want the note attached, by providing the name, ID, and type of the target entity. In this case, I used a contact as my target. The note.objectid.type is very important; it tells CRM the type of the target entity. In order to help reduce human error, the CRM API developers included a reference enum class called EntityName. This enum is updated if you create new custom entities and publish them.
- #4 The
objecttypecode property is a required field; without it, CRM will throw an exception.
You have to give the target entity's type. I recommend using the EntityName enum to prevent any errors. This may seem a bit redundant, I am not sure why we have to set the type again; if anyone knows, please let me know.
Finally, you will need to create the note to get the a GUID. The next step is to actually upload a file:
FileInfo pointer = new FileInfo( "c:/test.pdf");
FileStream fileStream = pointer.OpenRead();
byte[] byteData = new byte[(int)fileStream.Length];
fileStream.Read(byteData, 0, (int)fileStream.Length);
string encodedData = System.Convert.ToBase64String(byteData);
fileStream.Flush();
fileStream.Close();
UploadFromBase64DataAnnotationRequest upload =
new UploadFromBase64DataAnnotationRequest();
upload.AnnotationId = newNoteID;
upload.FileName = "test.pdf";
upload.MimeType = "application/pdf";
upload.Base64Data = encodedData;
UploadFromBase64DataAnnotationResponse uploaded =
(UploadFromBase64DataAnnotationResponse)myCRMService.Execute(upload);
- #1 You will need two classes: the
FileInfo class and the FileStream class.
The FileInfo class, because you can easily get the size of the file and the extension which will be needed at point #4 to identify the MIME type. The FileStream class, because you will need to convert the file to a base 64 string (not really sure why).
- #2 I don't need to state this, but make sure to close the file stream.
- #3 If you want to upload a file to an annotation, you will need to use the
UploadFromBase64DataAnnotationRequest class. This class is used only for annotation attachments.
The class will accept the ID of the annotation, you will also have to provide the filename.
- #4 The sticky point here is specifying the MimeType; this took me forever because you have to be very specific, otherwise CRM will not deliver the file correctly when you want to upload it.
I used the following MimeType list to search for the correct value based on the file extension.
- #5 In this step, you provide the upload request with the encoded base64 string.
- #6 Finally, you upload the file by calling the
crmService.Execute method and passing it the upload request.
If you have a large file to upload and many other tasks to perform afterwards, I suggest uploading the file asynchronously by calling the crmService.ExecuteAsync method.
I hope this article has helped you.
Feel free to contact me anytime if you need help or have any questions by leaving a comment on the article.