2

I am mapping Status Reason from CRM which is an Option Set to a Single Line of Text field on Sitecore. I have checked the Use Value Property

enter image description here

but it returned the integer value of the option set.

enter image description here

I have seen http://integrationsdn.sitecore.net/DynamicsCrmConnect/v1.2/cookbooks/synchronization/option-set-values/index.html for mapping option set values but it works the other way around, i.e., Sitecore to CRM. I tried creating a Read Version of the code as follows:

using Microsoft.Xrm.Sdk;
using Sitecore.DataExchange.DataAccess;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;


namespace DynamicsCrm
{
    public class EntityAttributeOptionSetValueReader : IValueReader
    {
        public EntityAttributeOptionSetValueReader(string attributeName)
        {
            this.AttributeName = attributeName;
        }

        public string AttributeName { get; private set; }

        public CanReadResult CanRead(object source, DataAccessContext context)
        {
            var canRead = false;
            var isGuess = false;
            if (source != null)
            {
                if (source is Entity)
                {
                    canRead = true;
                    isGuess = true;
                }
            }
            return new CanReadResult { CanReadValue = canRead, IsGuess = isGuess };
        }

        public ReadResult Read(object source, DataAccessContext context)
        {            
            var entity = source as Entity;
            if (entity != null)
            {
                if (entity.Attributes.ContainsKey(this.AttributeName))
                {
                    if (entity.Attributes[this.AttributeName] is OptionSetValue)
                    {
                        //var value2 = entity.Attributes[this.AttributeName] as OptionSetValue;
                        int value = (entity.Attributes[this.AttributeName] as OptionSetValue).Value;
                        //value2.Value = (int)value;
                        //return new ReadResult { ReadValue = 2 };

                        // Get the raw option set value and return the label
                    }
                }
                else
                {
                    entity.Attributes[this.AttributeName] = new OptionSetValue((int)value);
                    //return true;
                }
            }
            //return false;
        }
    }
}

However, I'm stuck with the Read method because I don't know what specifically is ReadValue since it's an object. I'm unfamiliar with this and cannot find examples in the documentation and I would really appreciate your guidance. As for DateTime, it doesn't map the correct value too and return the following:

enter image description here

There are no problems with strings and single line of texts. Thank you very much for your help!

EDIT:

Thanks to Vlad, here is my code I've patterned from http://integrationsdn.sitecore.net/DynamicsCrmConnect/v1.2/cookbooks/synchronization/option-set-values/add-value-writer.html

EntityAttributeValueAccessorConverterEx.cs

using System.Text;
using System.Threading.Tasks;
using Sitecore.DataExchange.Repositories;
using Sitecore.DataExchange.DataAccess;
using Sitecore.Services.Core.Model;
using Sitecore.DataExchange.Providers.DynamicsCrm.Converters.DataAccess.ValueAccessors;
using Sitecore.DataExchange.Providers.DynamicsCrm.Models.ItemModels.DataAccess;
using DynamicsCrm;

namespace DynamicsCrm
{
    public class EntityAttributeValueAccessorConverterEx : EntityAttributeValueAccessorConverter
    {
        public EntityAttributeValueAccessorConverterEx(IItemModelRepository repository) : base(repository)
        {
        }
        public override IValueAccessor Convert(ItemModel source)
        {
            var accessor = base.Convert(source);
            if (accessor != null && accessor.ValueReader == null)
            {
                var useValueProperty = base.GetBoolValue(source, EntityAttributeValueAccessorItemModel.UseValueProperty);
                if (useValueProperty)
                {
                    string attributeName = base.GetStringValue(source, EntityAttributeValueAccessorItemModel.AttributeName);
                    accessor.ValueReader = new EntityAttributeOptionSetValueReader(attributeName);
                }
            }
            return accessor;
        }
    }
}

EntityAttributeOptionSetValueReader.cs

using Microsoft.Xrm.Sdk;
using Sitecore.DataExchange.DataAccess;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;


namespace DynamicsCrm
{
    public class EntityAttributeOptionSetValueReader : IValueReader
    {
        public EntityAttributeOptionSetValueReader(string attributeName)
        {
            this.AttributeName = attributeName;
        }

        public string AttributeName { get; private set; }

        public CanReadResult CanRead(object source, DataAccessContext context)
        {
            var canRead = false;
            var isGuess = false;
            if (source != null)
            {
                if (source is Entity)
                {
                    canRead = true;
                    isGuess = true;
                }
            }
            return new CanReadResult { CanReadValue = canRead, IsGuess = isGuess };
        }

        public ReadResult Read(object source, DataAccessContext context)
        {            
            var entity = source as Entity;
            if (entity != null)
            {
                if (entity.Attributes.ContainsKey(this.AttributeName))
                {
                    if (entity.Attributes[this.AttributeName] is OptionSetValue)
                    {
                        //var value2 = entity.Attributes[this.AttributeName] as OptionSetValue;
                        string statusCodeStr = entity.FormattedValues[this.AttributeName];
                        //value2.Value = (int)value;
                        return new ReadResult(DateTime.Now) { ReadValue = statusCodeStr, WasValueRead = true };

                        // Get the raw option set value and return the label
                    }
                }
                else
                {
                    return new ReadResult(DateTime.Now) { ReadValue = String.Empty, WasValueRead = false };
                    //return true;
                }
            }
            //return false;
            return new ReadResult(DateTime.Now) { ReadValue = String.Empty, WasValueRead = false };
        }
    }
}

In the Converter Type in the template's standard value, I wrote DynamicsCrm.EntityAttributeValueAccessorConverterEx, DynamicsCrm. I tried debugging it (the DLL is in inetpub/wwwroot/sitecoreinstance/website/bin) but didn't hit the breakpoint. Does the code make sense or am I missing something? Thank you very much!

  • Code under 'if (accessor != null && accessor.ValueReader == null)' will not be performed. 'accessor.ValueReader' is not null. – Vlad Shpak Feb 6 '17 at 9:11
2

If you want to get string value instead of int value you need to update your reader with:

string statusCodeStr = entity.FormattedValues[this.AttributeName];

Here is debug result:

enter image description here

According to DateTime mapping. Adam Conn has already answered. The solution is to use ISO Date Value Reader for the transformer. POCO DateTime not mapping correctly in Data Exchange Framework

| improve this answer | |
  • Thanks a lot! The DateTime mapping is now working. As for the OptionSet I've deployed the code (please see edit) but nothing happened. I also can't debug it. Is the trigger to run the pipeline? Even though I attached it to w3wp it didn't hit the breakpoint. Please see edited question above. – Judah Endymion Feb 6 '17 at 6:48
  • 1. If you use your own template for the "EntityAttributeValueAccessorConverterEx" you need to add supported id. 2. You overrides "Convert" method of EntityAttributeValueAccessorConverter and use "base.Convert". accessor.ValueReader is not null in base class. It means all code under the "if" block will not be performed. 3. Use Value Property shouldn't be set – Vlad Shpak Feb 6 '17 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.