Monday, September 30, 2013

Now Store Images in CRM 2013

We got the first hint of the much awaited data type Image with the introduction of activity feeds where we were allowed to provide a profile image for a user. Though the Activity Feeds had it, it was still not available for other entities OOB or custom.

In CRM 2013, the Dynamics CRM Product team has moved a step further and made this data available to all entities custom and some of the OOB but with a catch. The catch being you can still have only one image associated per record This still serves the purpose in most common cases where you would like to store the contact or product image along with the record.

Let us see how to define this attribute in CRM and later check how to programmatically read/write the image attribute on the record.

By default CRM now ships with the image attribute added to the following OOB entities


Setting up an entity for Image:

A new setting is now available on the entity form “Primary Image”. Use this setting to enable the Image attribute. Setting it to none, will not enable this feature i.e the image will not be shown on the entity form.

If the Image feature is enabled, you will find an image container in the record header as can be seen below.


In the Contact Entity the Image feature is enabled by default. However though the image attribute has been added to the Sales Order entity, it is not enabled by default. You can enable it by customizing the entity and selecting the image attribute.

For Custom entities, you first need to add an image attribute.



Note: The attribute schema name is fixed to “entityimage” and cannot be modified.

Also there can be only one attribute of image data type per entity. Adding another will show the following error


Once the attribute is added, it is now available for selection on the Primary Image setting on the entity.

To show image on the form follow this steps:

Go to form customization - >> Form Properties ->> Go to Display tab ->> check the Image section ->> Show image in the form option as highlighted below then click ok. Save and publish.


Now create a record and check on the top left side as shown in the below screenshot. Click on the image to add/edit and browse new image


Programmatically Read/Write the Image to the record:

Reading entity records using Columns.AllColumns does not return the image attribute. You need to specifically list out the attribute for reading data stored in the image attribute.

Reading Image from a record:
//read the contact
                    var qry = from c in context.CreateQuery("contact")
                              orderby c.GetAttributeValue<string>("fullname")
                              select new
                                  {
                                      name = c.GetAttributeValue<string>("fullname"),
                                      id = c.GetAttributeValue<Guid>("contactid"),
                                      image = c.GetAttributeValue<byte[]>("entityimage")
                                  };

                    var contactid = qry.First().id;
                    var name = qry.First().name;

                    //read the image for the contact
                    byte[] data = (byte[]) qry.First().image;

                    //download the image
                    using (System.IO.FileStream fileStream = new FileStream(name + ".png", FileMode.OpenOrCreate))
                    {
                        fileStream.Write(data, 0, data.Length);
                    }

Add/Update the Image of a record:

//update the record with a new image
                    string path = @"C:\test.png";
                    byte[] uploaddata = null;

                    //download the image
                    using (System.IO.FileStream fileStream = new FileStream(path, FileMode.Open))
                    {
                        int size = (int) fileStream.Length ;
                        uploaddata = new byte[size];
                        fileStream.Read(uploaddata, 0, size);

                    }

                    Entity contact = context.CreateQuery("contact").Where(c => c.GetAttributeValue<Guid>("contactid").Equals(contactid)).First<Entity>();

                     //set the image data
                    contact.Attributes["entityimage"] =  uploaddata;

                    context.UpdateObject(contact);
                    context.SaveChanges();


Identify if an entity has image enabled:

The EntityMetadata now returns a property PrimaryImageAttribute that provides the name of the attribute that stores the image data.

Display the image in an IFRAME:

The image would always be cropped to a square with dimensions of 144x144 or less depending on the size of the image uploaded.

Not sure if this is the supported way, but you can display the image in an IFRAME using the “entityimage_url” property. It stores the link to the image. Using a hardcoded link the image could be displayed as shown below


Conclusion:

The next logical step would be to extend this design to allow for multiple image attributes per entity

1 comment: