Monday, December 3, 2007

How to attach a file to any CRM 3.0 entity

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:
1) Create or retrieve the entity that you want the file to be attached to.
2) Read the file steam and encode it to a Base64 string.
3) 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 contactID 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;

//#1
annotation note = new annotation();
note.subject = "my attachment";

//#2
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

//#4
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 objectid 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:

//#1
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);

//#2
fileStream.Flush();
fileStream.Close();

//#3
UploadFromBase64DataAnnotationRequest upload = new UploadFromBase64DataAnnotationRequest();
upload.AnnotationId = newNoteID;
upload.FileName = "test.pdf";

//#4
upload.MimeType = "application/pdf";

//#5
upload.Base64Data = encodedData;

//#6
UploadFromBase64DataAnnotationResponse uploaded = (UploadFromBase64DataAnnotationResponse)myCRMService.Execute(upload);

#1
You will need two classes the FileInfo class and the FileStream class.

The FileInfo, because you can easily get the size of the file and the extension which will be needed at point #4 to identify the mimetype.
The FileStream class because you will need to convert the file to a base64 string (not really sure why).

#2
I don't need to state this but make sure to close the filestream.

#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 Asynchroniously by calling the crmService.ExecuteAsync method.

I hope you this article has helped you.

Labels: , , , , ,

4 Comments:

At December 28, 2007 at 12:13 PM , Anonymous Anonymous said...

Hi do you have the code download a file that is attached with any entity, using asp.net(C#) as a front end

 
At December 28, 2007 at 12:20 PM , Blogger Oshri Cohen said...

I have a post on how to download email attachments.

I will try and write a quick post later today.

Otherwise, query all of the annotations for an entity and based on the AnnotationID create a link to download the file.

the link is:
/Activities/Attachment/download.aspx?AttachmentType=5&AttachmentID={ID of attachment}

 
At January 7, 2008 at 2:55 AM , Anonymous Anonymous said...

I am able to attach the file to a Note in CASE.

But I am not able to know how to download the file attached to the Note. Can any body help me on this.

I am not able to find any attahment Id in the response

 
At January 8, 2008 at 9:44 AM , Blogger Oshri Cohen said...

I believe the attachmentID is the annotationID (the id of the note)

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home