This seems like a very simple requirement. But when it comes to implementation, you might find that fitting this requirement into an already existing functionality such as the CRM the annotations (notes) facility, is not as strait forward as it sounds.
Wanting to display a user avatar, a company logo or even a product image is a very acceptable requirement. And since CRM does not allow such facility out of box, I figured it would be nice to show you how this could be done in just a few minutes.
The simplest solution would be to place all images under the ISV folder then create an IFRAME, where desirable, and set its SRC attribute to a specific URL through script. This also requires the user or application to adhere to a strict naming convention such as a contact FirstName + LastName.gif or an account accountid.jpg or accountnumber.bmp and so forth.
For the sake of discussion the rest of my code bits would refer to the account entity and presenting an account logo inside a dedicated iframe e.g. IFRAME_accountlogo.
Your code might look like the following lines:
var accountLogo = "/isv/images/accounts/missing.gif";
If (crmForm.accountnumber.DataValue != null)
{
accountLogo = "/isv/images/accounts/" + crmForm.accountnumber.DataValue + ".gif";
}
document.all.IFRAME_accountlogo.src = accountLogo;
This process is quite limiting since it requires the involvement and communication with a power user or an administrator who need to put the images in their respective folders. They also need to manage the changes and deletions of images from that folder for obvious reasons. By now this looks like a bad strategy and we need to come up with a better and more manageable solution.
Can I upgrade the above solution? The answer is of course you can! You can automate this type of process by allowing the user to upload the image to a specified location and saving the image name to a new dedicated attribute you set on the entity e.g new_accountimagename.
The client side script might look like the following lines:
var accountLogo = "/isv/images/accounts/missing.gif";
if (crmForm.new_accountimagename.DataValue != null)
{
accountLogo = "/isv/images/accounts/" + crmForm.new_accountimagename.DataValue;
}
document.all.IFRAME_accountlogo.src = accountLogo;
You might argue, and rightly so, that this type of solution does not completely resolve the need for our administrator to manage these folders, and CRM already has an uploading facility (for annotations), so why not use that?!
Obviously this type of solution only answers a partial requirement and we need to come up with a better one yet again.
So how do you take advantage of CRM’s annotation facility? And how can you bind the upload process to an IFRAME?
If you ask a developer, with no relevant knowledge of dynamics, how to do that with asp.net he would probably tell you that you need to read the binaries from the database and render them back to the calling image on the client.
e.g.
Wait a minute, this looks very familiar. And indeed it is! as CRM already uses this type of functionality inside the email entity. When you track an email with an inline image from outlook client CRM saves the inline image as attachment and present it inside the email body.
e.g.
So I asked my self why would ms send the attachment entity type if this type of functionality is only for attachments? And as it appears if you change the AttachmentType parameter from 1001 to 5 (annotation object type code) and set the attachmentid to an annotationid you receive the desired results.
e.g.
And your onload script should look like:
var annotationid = getAccountLogoAnnotationId();
var iframeDoc = document.all.IFRAME_accountlogo.contentWindow.document;
var image = iframeDoc.createElement('img');
image.src = prependOrgName("/Activities/Attachment/download.aspx?AttachmentType=5&AttachmentId=") + annotationid;
iframeDoc.body.appendChild(image);
The getAccountLogoAnnotationId function should use a fetchxml to retrieve the annotationid. The best way of doing that is telling the user to upload the image under a well known name and creating a constant fetchxml request as follows.
Is this type of solution consider supported? My first gut feeling is actualy yes. I don’t see why ms would downgrade this type of solution to only support email attachment. The only thing that might change is the actual url. This seems a good enough solution for a 5 minute work.
Eventually you might mimic the entire functionality your self by creating a download.aspx page, reading the image binaries from the filtered annotation view and render the result your self.
For a complete example of how to use an Ajax fetch call to CRM
follow this post.