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
but it returned the integer value of the option set.
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:
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!