AutoMapper Configuration and Setup for Dynamics CRM

Posted on

The scenario

When it comes to mapping objects within .Net AutoMapper is a popular choice.  AutoMappers wiki has many examples of moving between complex to flat structures; custom resolvers for bespoke situations and more.  But implementing mappings between your custom .net typed objects and CRM entities can be a little more complicated, especially when it comes to CRM types like OptionSetValues.

So here’s a tutorial to show you how to setup AutoMapper where either the source or the destination is of CRM entity type.

 

 

A few assumptions:

Firstly this walkthrough assumes that you already understand how to connect to a CRM organisation programmatically.  Here is a link to one of the quickest ways to get up and running. Also I won’t be going into the intricacies of AutoMapper configuration or inner workings, there is a excellent getting started guide here. Finally, the early bound class used to store CRM types has already been generated; nice tutorial here on how to do it.

So without further ado.  This walkthrough will be based on creation of contact entity records and an equivalent contactDTO object.

First things first – Setup

Let’s get AutoMapper and CRM dll’s installed from nuget.  The source code attached will restore them for you automatically but here are a list of the dependencies.

AutomapperBlog1

So with our packages in place let’s take a quick look at the details and more specifically types used in out object mappings.

We have a .net class called “CustomContact”, unsurprisingly.

public class CustomContact
{
     public string FirstName { get; set; }
     public string LastName { get; set; }
     public int GenderCode { get; set; }
}

In addition, we also have our CRM generated entity type “Contact” which has all the property attributes normally associated with this CRM entity.  More specifically here is the type used for GenderCode.

public Microsoft.Xrm.Sdk.OptionSetValue GenderCode
{
     get
     {
          return this.GetAttributeValue<Microsoft.Xrm.Sdk.OptionSetValue>("gendercode");
     }
     set
     {
          this.OnPropertyChanging("GenderCode");
          this.SetAttributeValue("gendercode", value);
          this.OnPropertyChanged("GenderCode");
     }
}

Firstname and Lastname will be direct mappings (AutoMapper works on the basis of a convention naming algorithm) but what about GenderCode?

Moving On – The problem

Typically, with AutoMapper configuration we would create a mappings for each direction i.e where source and destination could be either CRM or a custom object.  We want to be able to map both ways, so our configuration might look something like.

 

Mapper.CreateMap<Contact, CustomContact>()
.ForMember((dest => dest.GenderCode), opt => opt.MapFrom(src => (src.GenderCode)));

Mapper.CreateMap<CustomContact, Contact>()
.ForMember(dest => dest.GenderCode, opt => opt.MapFrom(src => src.GenderCode));

 

However, when moving from Contact to Custom, this throws an error as per below complaining that OptionSetValues mappings are unsupported.

AutomapperBlog2

In addition if our source was a custom object and destination was our CRM entity we get a mismatch error exception thrown.  Existing configuration for this would look like.

Getting there – The solution

We need new configuration when moving between our different types.

When the source is a custom object and the destination is a CRM entity, the required changes are pretty straight forward.  During the mapping create a new optionsetvalue for your attribute of choice.

Mapper.CreateMap<CustomContact, Contact>()
.ForMember(dest => dest.GenderCode, opt => opt.MapFrom(src => new OptionSetValue(src.GenderCode)));

 

Mapping when the source is a CRM entity and the destination is a custom object structure is slightly more complicated as we are required to use a custom type convertor to map our values correctly.

Mapper.CreateMap<OptionSetValue, int>().ConvertUsing(new OptionSetTypeConverter());
Mapper.CreateMap<Contact, CustomContact>();

I have created a custom type convertor for OptionSetValues that will be applied when the source type is optionset and the destination is of type int.

 

public class OptionSetTypeConverter : ITypeConverter<OptionSetValue, int>;
{
     public int Convert(ResolutionContext context)
     {
          try
          {
               OptionSetValue op = context.SourceValue as OptionSetValue;
               return System.Convert.ToInt32(op.Value);
          }
          catch (Exception ex)
          {
               //Handle your exception here as you wish
               throw;
          }
     }
}

Once applied this will be applied where the source and destination types match the mapping rule.

Finally

If you setup and run the attached project you will see that 2 CRM contact entities that have been created with different AutoMapper configuration – moving from CRM to custom objects and vice versa.

AutomapperBlog3

Within CRM, after an advanced find, we can see our 2 newly created entities confirmed and more importantly that the correct optionsetvalue is in place for the contact.

AutomapperBlog4

Check out the attached code and if you have any comments or issues please feel free to get in touch or post below.  Happy programming.

Resources:

Here is a list of CRM types associated with elements like picklist, party lists, entities etc.
http://msdn.microsoft.com/en-us/library/gg328507%28v=crm.5%29.aspx#

Share on FacebookShare on LinkedInTweet about this on TwitterEmail this to someonePin on PinterestPrint this pageShare on Google+Share on Reddit

Tags: , , , ,


Leave a Reply

Your email address will not be published. Required fields are marked *