·
5 min read

Tips & Tricks: Displaying Contact Images in Microsoft Dynamics CRM

In another of our guest blog series, CRM MVP Jürgen Beck provides a developer’s view demonstrating out customizable Microsoft Dynamics CRM 3.0 is. This post is provided “AS IS” with no warranties and confer no rights. You assume all risk for your use.

Wouldn’t it be nice to see some pictures of your customer when you open the contact form?

clip_image002

These pictures could be stored as jpg-attachment in the notes of your contact:

clip_image004

The solution behind this is to create a little ASP.NET-web application which should be displayed in an IFrame in your contact form:

clip_image006

The tricky thing here is to get a one-column-sized IFrame. The solution is to replace the first section by a custom section with a “Fixed Field Width” Section Layout and a “Two Columns (1:1)” Column Format.

clip_image008

Now you can create the IFrame, which have to be linked to your web application:

clip_image010

In the Layout properties you see that you have a “One column” Layout.

clip_image012

But the most important thing is to create an ASP.NET web application with Visual Studio 2008 or Visual Web Developer 2008 Express Edition. Sorry, but in this context I cannot show you the basics, but if you are a little bit experienced with ASP.NET this should be no problem for you.

Create a Project with a name like “CrmExtensions” with the following files and the references to the files “microsoft.crm.sdk.dll” and “microsoft.crm.sdktypeproxy.dll” from the Microsoft Dynamics CRM 4.0 SDK.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ShowImageAttachments.aspx.cs" Inherits="CrmExtensions. ShowImageAttachments" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Panel ID="panelPictures" runat="server">
    </asp:Panel>
    </form>
</body>
</html>

ShowImageAttachments.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.Sdk;

namespace CrmExtensions
{
    public partial class ShowImageAttachments : System.Web.UI.Page
    {
        CrmHelper myCrmHelper = new CrmHelper();

        protected void Page_Load(object sender, EventArgs e)
        {
            Guid id = Guid.Empty;
            int objecttypecode = 0;
            try
            {
                id = new Guid(Request.QueryString["id"]);
                objecttypecode = Int16.Parse(Request.QueryString["type"]);
            }
            catch
            {
                // This can be the Guid of a contact with pictures you want to display for new contacts.
                id = new Guid("{2EE9EA21-B900-DD11-B6E8-001871E4CE73}");
                objecttypecode = 2;
            }
            ColumnSet columns = new ColumnSet(new string[] { "filesize", "filename" });
            List<DynamicEntity> annotations = myCrmHelper.GetDynamicEntities("annotation", new string[] { "objectid", "objecttypecode" }, new object[] { id, objecttypecode }, columns);
            List<Guid> annotationids = new List<Guid>();
            foreach (DynamicEntity annotation in annotations)
            {
                Guid annotationid = annotation.GetKeyValue();
                string filename = annotation.GetString("filename");
                int filesize = annotation.GetCrmNumberValue("filesize");
                // Only small jpg-files are allowed
                if (filename.ToLower().EndsWith("jpg") && filesize < 500000)
                {
                    string imageUrl = "ShowImageAttachment.aspx?id=" + annotationid.ToString();
                    // This is the download-URL to the file itself to get the original file instead of a smaller version.
                    string navigateUrl = "/ComBeck/Activities/Attachment/download.aspx?AttachmentType=5&AttachmentId=" + annotationid;
                    HyperLink hl = new HyperLink();
                    hl.ImageUrl = imageUrl;
                    hl.NavigateUrl = navigateUrl;
                    hl.Target = "_self";
                    hl.Text = filename + " (" + (filesize / 1000).ToString("#,##0") + " KB)";
                    hl.ToolTip = filename + " (" + (filesize / 1000).ToString("#,##0") + " KB)";
                    panelPictures.Controls.Add(hl);
                }
            }
        }
    }
}

ShowImageAttachment.aspx:

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”ShowImageAttachment.aspx.cs” Inherits=”CrmExtensions. ShowImageAttachment” %>

ShowImageAttachment.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace CrmExtensions
{
public partial class ShowImageAttachment : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CrmHelper myCrmHelper = new CrmHelper();
Guid annotationid = new Guid(Request.QueryString[“id”]);
CrmService crmService = myCrmHelper.GetCrmService();
annotation crmAnnotation = (annotation)crmService.Retrieve(“annotation”, annotationid, new AllColumns());
byte[] picture = System.Convert.FromBase64String(crmAnnotation.documentbody);
System.IO.MemoryStream ms = new System.IO.MemoryStream(picture);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms);
int height = 150;
int width = height * bmp.Width / bmp.Height;
Response.ContentType = crmAnnotation.mimetype;
if (bmp.Height > height)
{
System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(ms);
System.Drawing.Bitmap bmPhoto = new System.Drawing.Bitmap(width, height, bmp.PixelFormat);
bmPhoto.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;
grPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, width, height), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel);
MemoryStream mm = new MemoryStream();
bmPhoto.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
imgPhoto.Dispose();
bmPhoto.Dispose();
grPhoto.Dispose();
}
else
{
bmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
bmp.Dispose();
}
}
}

CrmHelper.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Data;
using System.Data.SqlClient;
using System.Text;

using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using System.Collections;
using Microsoft.Crm.Sdk.Metadata;
using System.IO;

namespace CrmExtensions
{
public partial class CrmHelper
{

public CrmService GetCrmService()
{
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 0; //Active Directory
token.OrganizationName = “ComBeck”;
CrmService service = new CrmService();
service.Url = “http://crm/mscrmservices/2007/crmservice.asmx”;
service.UseDefaultCredentials = true;
service.PreAuthenticate = true;
service.CrmAuthenticationTokenValue = token;
return service;
}

public List<DynamicEntity> GetDynamicEntities(string entityName, string[] attributes, object[] values, ColumnSetBase columns)
{
CrmService crmService = GetCrmService();
RetrieveMultipleRequest rmRequest = new RetrieveMultipleRequest();
QueryBase queryBase = null;
if (attributes == null)
{
QueryExpression query = new QueryExpression();
queryBase = query;
}
else
{
QueryByAttribute query = new QueryByAttribute();
query.Attributes = attributes;
query.Values = values;
queryBase = query;
}
queryBase.EntityName = entityName;
if (columns is AllColumns)
{
queryBase.ColumnSet = columns;
}
else if (columns is ColumnSet)
{
queryBase.ColumnSet = columns;
}

rmRequest.Query = queryBase;
rmRequest.ReturnDynamicEntities = true;
RetrieveMultipleResponse rmResponse = (RetrieveMultipleResponse)crmService.Execute(rmRequest);
List<DynamicEntity> dynamicEntities = new List<DynamicEntity>();
foreach (BusinessEntity be in rmResponse.BusinessEntityCollection.BusinessEntities)
{
dynamicEntities.Add((DynamicEntity)be);
}
return dynamicEntities;
}
}
}

This ASP.NET project has to be saved under the ISV subfolder of your CRM-folder like “C:\Inetpub\wwwroot\ISV\ComBeck”. The folder “ComBeck” has now to be configured in IIS as Application.

clip_image014

If you get a “MultipleOrganizationSoapHeaderAuthenticationProvider” exception please take care to register the file “Microsoft.Crm.WebServices.dll” from folder “C:\Inetpub\wwwroot\bin” in the Global Assembly Cache (GAC). Please do an iisreset after this.

DynamicEntityExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.Sdk.Metadata;
namespace CrmExtensions
{
public static class DynamicEntityExtensions
{
public static CrmNumber GetCrmNumber(this DynamicEntity entity, string propertyName)
{
return entity.GetCrmNumber(propertyName, true);
}
public static CrmNumber GetCrmNumber(this DynamicEntity entity, string propertyName, bool nullIfEmpty)
{
if (entity.Properties.Contains(propertyName))
{
CrmNumber crmNumber = (CrmNumber)entity.Properties[propertyName];
if (crmNumber.IsNullSpecified && crmNumber.IsNull && nullIfEmpty)
{
return null;
}
else
{
return crmNumber;
}
}
else
{
if (nullIfEmpty)
{
return null;
}
return new CrmNumber { IsNullSpecified = true, IsNull = true };
}
}
public static int GetCrmNumberValue(this DynamicEntity entity, string propertyName)
{
CrmNumber crmNumber = GetCrmNumber(entity, propertyName);
if (crmNumber == null)
{
return 0;
}
else
{
return crmNumber.Value;
}
}
public static string GetString(this DynamicEntity entity, string propertyName)
{
if (entity.Properties.Contains(propertyName))
{
return entity.Properties[propertyName].ToString();
}
else
{
return “”;
}
}
public static Key GetKey(this DynamicEntity entity)
{
foreach (object property in entity.Properties)
{
if (property is KeyProperty)
{
return ((KeyProperty)property).Value;
}
}
return null;
}
public static Guid GetKeyValue(this DynamicEntity entity)
{
Key key = GetKey(entity);
if (key != null)
{
return key.Value;
}
else
{
return Guid.Empty;
}
}
}
}