Ok, a lot of people have been asking on the forums about how to display images that are attached to your CRM entity. To help with that, here is a web-resource that will display images and fit them to the area allotted. If you have more than 1 picture it will show some previous and next buttons below the photo. The general idea here is to not only display an image on the form, but work across multiple browsers (and systems). Leveraging JQuery and the REST SDK, this attachment image web-resource is a quick-and-easy image control, granted it doesn’t include all of the features the Silverlight CRMAttachmentImage control does.
Below you can see an example of what it looks like. YOu can download the managed solution here and the unmanaged solution here.

You can specify the height and width in the parameters.
height:200|width:100
The image will resize to scale.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Image Browser</title>
<script type="text/javascript" src="jq_1.7.2.min.js">
</script>
<script type="text/javascript">
//<![CDATA[
$.fn.sandbox = function(fn) {
var element = $(this).clone(), result;
// make the element take space in the page but invisible
element.css({visibility: 'hidden', display: 'block'}).insertAfter(this);
// to override any display: none !important you may have been using
element.attr('style', element.attr('style').replace('block', 'block !important'));
result = fn.apply(element);
element.remove();
return result;
};
var GetDataParams = function()
{ //modified version of: http://technet.microsoft.com/en-us/library/gg327945.aspx
//Get the any query string parameters and load them
//into the vals array
var vals = new Array();
if (location.search != "")
{
vals = location.search.substr(1).split("&");
for (var i in vals)
{
vals[i] = vals[i].replace(/\+/g, " ").split("=");
}
//look for the parameter named 'data'
var found = false;
for (var i in vals)
{
if (vals[i][0].toLowerCase() == "data")
{
found = true;
var datavals = decodeURIComponent(vals[i][1]).split("|");
for (var i in datavals)
{
datavals[i] = datavals[i].replace(/\+/g, " ").split("=");
}
break;
}
}
if (found) { return datavals; }
}
return null;
}
var ImageBrowser = function () {
function getImage() {
function getRecords(query, successCallback) {
$.ajax({
type: "GET",
async: true,
contentType: "application/json; charset=utf-8",
url: query,
datatype: "json",
beforeSend: function (request) {
request.setRequestHeader("Accept", "application/json");
},
success: function(data, textStatus, xhr) {
if (data && data.d && data.d.results) {
successCallback(data.d.results)
}
},
error: function (xhr, textStatus, errorThrown) {
alert("Error : " +
xhr.status + ": " +
xhr.statusText);
}
});
}
function buildQuery(s,c,f,t,p) {
function getServerUrl() { // From CrmRestKit.js
var localServerUrl = window.location.protocol + "//" + window.location.host;
var context = parent.Xrm.Page.context;
if (context.isOutlookClient() && !context.isOutlookOnline()) {
return localServerUrl;
}
else {
var crmServerUrl = context.getServerUrl();
crmServerUrl = crmServerUrl.replace(/^(http|https):\/\/([_a-zA-Z0-9\-\.]+)(:([0-9]{1,5}))?/, localServerUrl);
crmServerUrl = crmServerUrl.replace(/\/$/, "");
}
return crmServerUrl;
}
return getServerUrl() + "/XRMServices/2011/OrganizationData.svc/" + s + "/?" +
"&$filter=" + f +
"&$select=" + c.join(',') +
"&$top=" + t +
"&$skip=" + p;
}
function updateImage(records) {
var foundpicture = false;
var picture;
if (records.length<1) {
$("#picture").css("display","none");
picture = $("#nopicture");
picture.css("height",200);
picture.css("width",120);
} else {
foundpicture = true;
var source = "data:" + records[0].MimeType + ";base64," + records[0].DocumentBody;
picture = $("#picture");
picture.css("height","auto");
picture.css("width","auto");
}
picture.css("display","none");
var pHeight = ImageBrowser.MaxHeight;
var pWidth = ImageBrowser.MaxWidth;
if (foundpicture) { picture.attr("src",source); }
var pictureSize = picture.sandbox(function(){ return {height: this.height(), width: this.width()}; });
var scale = 1;
if (pictureSize.height>pHeight) {
if ((pictureSize.width-pWidth)>(pictureSize.height-pHeight)) {
scale = pictureSize.width / pWidth;
} else {
scale = pictureSize.height / pHeight;
}
}
if (scale!=1) {
var nh = pictureSize.height / scale;
var nw = pictureSize.width / scale;
picture.css("height",nh + "px");
picture.css("width",nw + "px");
}
picture.css("display","block");
}
function updateFirstLast(records) {
ImageBrowser.First = (ImageBrowser.Index==0) ? true : false;
ImageBrowser.Last = (records.length<1) ? true : false;
$("#previous").css("display",ImageBrowser.First ? "none" : "inline");
$("#next").css("display",ImageBrowser.Last ? "none" : "inline");
}
var setName = 'AnnotationSet';
var columns = ['DocumentBody','MimeType'];
var filter = "ObjectId/Id eq (guid'" + ImageBrowser.EntityId + "') " +
"and startswith(MimeType,'image/') " +
"and ObjectTypeCode eq '" + ImageBrowser.EntityName + "'";
var top = 1;
var skip = ImageBrowser.Index;
getRecords(buildQuery(setName,columns,filter,top,skip+1),updateFirstLast);
getRecords(buildQuery(setName,columns,filter,top,skip),updateImage);
}
function previous() {
if (ImageBrowser.Index>0) {
ImageBrowser.Index = ImageBrowser.Index - 1;
getImage();
}
}
function next() {
if (ImageBrowser.Last==false) {
ImageBrowser.Index = ImageBrowser.Index + 1;
getImage();
}
}
function init() {
ImageBrowser.MaxWidth = $("body").width();
ImageBrowser.MaxHeight = $("body").height();
var data = GetDataParams();
for (var i in data)
{
switch (data[i][0].toLowerCase())
{
case 'height':
var h = parseInt(data[i][1]);
var ph = $("body").height();
if (h<ph) {
ImageBrowser.MaxHeight = h;
} else {
ImageBrowser.MaxHeight = ph;
}
break;
case 'width':
var w = parseInt(data[i][1]);
var pw = $("body").width();
if (w<pw) {
ImageBrowser.MaxWidth = w;
} else {
ImageBrowser.MaxWidth = pw;
}
break;
$("#area").height(parseInt(data[i][1])); break;
}
}
getImage();
}
return {
EntityId: parent.Xrm.Page.data.entity.getId(),
EntityName: parent.Xrm.Page.data.entity.getEntityName(),
First: true,
MaxHeight: 0,
MaxWidth: 0,
Last: false,
Index: 0,
Previous: previous,
Next: next,
Initialize: init
};
}();
function next() { ImageBrowser.Next(); }
function prev() { ImageBrowser.Previous(); }
function onload() {ImageBrowser.Initialize(); }
//]]>
</script>
<style type="text/css">
/*<![CDATA[*/
html, body, div {
background-color: rgb(246, 248, 250);
font-family: "Tahoma", "Helvetica", "Arial", "Verdana", "sans-serif";
font-size:9px;
padding: 0px;
margin: 0px;
}
body {
margin: 3px;
}
body, div.area {
text-align: center;
}
img {
border-style: none;
}
#nopicture {
border: solid 1px black;
font-size: 9px;
text-align:center;
}
#nopicture p {
padding-top: 30%;
}
/*]]>*/
</style>
<meta charset="utf-8" />
</head>
<body onload="onload();" contenteditable="true">
<div id="area">
<table cellpadding="0" cellspacing="0">
<tr><td id="picturearea" colspan="2"><img id="picture" class="picture" src="" /><div id="nopicture" style="display:none;"><p>No Pictures</p></div></td></tr>
<tr>
<td style="text-align:right;"><a id="previous" href="javascript:prev();" style="display:none"><img src="img_icons/previous.png" /></a></td>
<td style="text-align:left;"><a id="next" href="javascript:next();" style="display:none"><img src="img_icons/next.png" /></a></td>
</tr>
</table>
</div>
</body>
</html>
Thanks to Willington’s Blog for the sandbox jquery function.

Ok… while images in my project work and display properly, the frame sometimes goes off of the page. I’m not sure why. You could always hide the entire control instead of displaying a No Pictures message. Any thoughts?
How are you meant to add this to the contact.
I have inserted the img_browser.html as a webresource but this doesn’t show any buttons and I can’t resize it.
do I need to add this as an Iframe?
also is it the img_browser.html I should be using?
Thanks
It is the img_browser.html you should be using and it will just show images in your attachments (notes) on the same entity. So you will need some images uploaded to your notes. Once you drop it onto the page, I’d suggest making it more rows, like 10 rows, and then see if it works. It is only going to add buttons below the image if you have multiple images atached to the entity in the notes.
Hi,
I have added the img_browser.html as a webresource to my contact form, however it displays a Error: 404: Not Found.
I have attached a image to the Notes section.
Any ideas?
Thanks
Clayton, I have tested it in both CRM Online and CRM OnPremise. What is your setup? Online/OnPremise, http/https, etc. What form are you dropping it on, did you publish after adding the web-resource.
I have followed all of the steps ( I think correctly) and within my CRM entity, in this case ‘accounts’, the image is not displaying correctly. When I have no images attached in the notes section I see “No Pictures”, however when I have attached an image all I get is a red ‘X’.
Additionally, when I add multiple images I do see the green arrows indicating that there are more than one image available but I again only see the red ‘X’.
Any suggestions?
At least we know it is browsing the files and retrieving the information properly. What kind of images are you uploading? I’d like to test it with the same type of files and see if I can replicate the issue. If not, then I will ask for those files to see if the same thing happens in my system.
On a side note I have tested it with gif images and png images. (I prefer png images).
I have used .gif, .jpeg, .png, .bmp with the same red x result. Could I have messed this up when loading the web resource?
The only reason it wouldn’t show properly is becasue the mime type or data is not being read correctly. How did you load the browser?
I used your solution,it works well but after closing the records only i’am getting the image. when i try to create a new records,it results in 404:BAD REQUEST.
Help me to resolve this?
Hi
Same problem here, did you find the way to solve this?
Where are you getting a 404? Is it part of the request? Is it in a window?
I get this error too. It only happens when I try to create a new record which is using the solution. Once I have saved the record though, the 404: Bad request error does not show up again. Can you please help?!
Thanks for your useful post. I am also facing the same problem as above people.Like , i get a red x mark and the symbols of next and previous . but i am not getting the image… Please send the correct method to use the control…
Thanks and regards,
Mohsinkhan
I user your solution and it works fine – thanks
I like it more than the silverlight solution.
One Question – I dont know where to set the witdth and height parameter – can you describe where?
Thanks
bernhard
Yes, you set them on the parameters of the web-resource when you put it on the page.
Works great, thanks!
This works great although I get two Error 400 : Bad Request
How do I display the name of the image on the form?
thanks
Scott
This works great although I get two Error 400 : Bad Request on a new entry form
How do I display the name of the image on the form?
thanks
Scott
Good day. When try to create new entry get errot 400: Bad request. In ready enrty all works fine. How to fix it?
Works well apart from 400 Errors when loading a new page. How would i display the filename of the image?
thanks
Scott
Hi
I like image browser very much. However while it works very well on IE 8 and 9 it does not work on IE 7. The line which is causing the problem is line 142 – picture.css(“display”,”block”); Do you have any idea why IE 7 will not execute this line? Alternativelly do you have any work-around we can implement to overcome this problem. Thanks!
Ruth