March 19, 2007

Dates in CRM Queries

It's pretty simple to build query expressions from CRM web service. Until you get to dates. You have lots of different ConditionOperator types like On, OnOrAfter, OnOrBefore, ThisWeek, Last7Days etc. But what about the values?

The problem is that you can't add a DateTime object to the values array of the ConditionExpression. If you do you'll most likely get the super duper error "Server was unable to process request". And what is more! The exception data reveals us the intriguing reason: "Invalid argument." DOH!

You have to pass the DateTime as string and parse it with "s" parameter. This is language-neutral and the CRM Server should be able to parse it regardless of the regional settings.


ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "new_duedate";
condition.Operator = ConditionOperator.OnOrAfter;
condition.Values = new string[] { DateTime.Now.ToString("s") };



March 13, 2007

How to copy an annotation

To copy notes wit or without attachments I have prepared this snippet.

//Copy attributes
annotation newAnnotation = new annotation();
newAnnotation.langid = sourceAnnotation.langid;
newAnnotation.notetext = sourceAnnotation.notetext;
newAnnotation.subject = sourceAnnotation.subject;
newAnnotation.objecttypecode = new EntityNameReference();
newAnnotation.objecttypecode.Value = destinationEntityName;

//Set the destination entity ID
newAnnotation.objectid = new Lookup();
newAnnotation.objectid.type = destinationEntityName;
newAnnotation.objectid.Value = destinationEntityId;

//Create annotation
Guid newAnnotationId = _crmService.Create(newAnnotation);
if (sourceAnnotation.isdocument.Value)
byte[] data = GetAnnotationAttachment(sourceAnnotation.annotationid.Value);
string base64data = System.Convert.ToBase64String(data);
AddAttachment(newAnnotationId, base64data, sourceAnnotation.mimetype, sourceAnnotation.filename);

The code for GetAnnotationAttachment is here.

The code for AddAttachment is here.

How to add an attachment

To upload an attachment I have prepared the following function:

private void AddAttachment(Guid parentAnntotationId, string attachmentBase64Data, string mimeType, string attachmentFileName)
UploadFromBase64DataAnnotationRequest upload = new UploadFromBase64DataAnnotationRequest();
upload.AnnotationId = parentAnntotationId;
upload.FileName = attachmentFileName;
upload.MimeType = mimeType;
upload.Base64Data = attachmentBase64Data;


How to get mime type? Previous post

Finding the file's mime type (MimeType)

I was looking for this for some time now. Simple, but beautiful solution:

public string GetMimeType(byte[] fileBytes)
ContentInfo info = new ContentInfo(fileBytes);
return info.ContentType.Value;
return "application/octet-stream";

How to get (download) an attachment

If you want to get an attachment from a note, then you have to get it using HTTP call. The following function returns an array of bytes that can be saved into a stream or you can convert it to Base64String (System.Convert.ToBase64String(myBytes)) if you want to save it again in CRM.

private byte[] GetAnnotationAttachment(Guid annotationId)
Guid attachid = annotationId;
int objecttypecode = 5;
//Annotation attachment OTC
string url = _serverUrl + "Activities/Attachment/download.aspx?AttachmentType=" + objecttypecode.ToString() + "&AttachmentId=" + attachid.ToString();
System.Net.WebClient myWebClient = new System.Net.WebClient();
myWebClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
return myWebClient.DownloadData(url);

March 12, 2007

HTTP status 401: Unauthorized error

I wrote some callouts that use CRM web service for reading some additional data.

Man I was furious! On the test system it worked, on the production I got the 401 unauthorized error.

I Goggled a bit and then I tried the simplest solution:

  • Comment out the code: crmWebService.PreAuthenticate = true;

And it worked!

Guess what? This code was copied from Microsoft CRM 3.0 SDK.

Callout setting files

I created a callout, but I wanted to have an additional XML settings file that can be changed on live system without restarting all necessary services.

You have two options:

  • You can hardcode the full path to the file (bad solution)
  • You can read the file from the "running folder"

The default running folder is:
%windows install folder%/system32/inetsrv.

So put your XML file in this folder and read it from the callout using:

XmlDocument settings = new XmlDocument();

That's it folks!