﻿#### 

Working on integration with Dynamics CRM implementation, in some cases we had to have something more than a simple field cope from CRM to Sitecore and we need to do some manipulations with data before saving it. For example, we have an address field in the CRM, but we want to store geographical coordinates instead. Solution below describes how we can do that.

First of all we need to implement a custom field reader with a custom field converter:

```

using Sitecore.DataExchange.DataAccess;

namespace Example
{
    public interface IBaseValueReader: IValueReader
    {
        string AttributeName { get; set; }
    }
}
  
```

AddressFieldReader:

```
      
using System;
using Sitecore.DataExchange.DataAccess;
using Sitecore.DataExchange.Repositories;

namespace Example
{
    public class AddressFieldReader : IBaseValueReader
    {
        public string AttributeName { get; set; }
        public IItemModelRepository Repository { get; private set; }
        public ExampleFieldReader(IItemModelRepository repository)
        {
            Repository = repository;
        }

        public CanReadResult CanRead(object source, DataAccessContext context)
        {
            return new CanReadResult()
            {
                CanReadValue = true
            };
        }

        public ReadResult Read(object source, DataAccessContext context)
        {
            object result = (object)null;

            var sourceObject = source as Microsoft.Xrm.Sdk.Entity;
            if (sourceObject != null &&  AttributeName != null)
            {
                object value;

                //Try to read attribute by the attribute name 

                if (sourceObject.Attributes.TryGetValue(AttributeName, out value))
                {

                    //Then you need to cast it to the address field type

                    var searchObject = value as Microsoft.Xrm.Sdk.Money; //It is example. You need to debug and see which type you exactly get. 

                    //Then you need to check if field is not null and have value.

                    if (searchObject != null && searchObject.Value != Decimal.Zero)
                    {
                        var fieldValue = searchObject.Value;

                        //IMPORTANT!!!
                        //IMPORTANT!!!
                        //IMPORTANT!!! Now, when you got a value of field, you can use any API to get Geo Latitude and Longitude. It can be some GeoAPI.

                        // Your code here:

                        var geoLocation = fieldValue; 

                        //Then you should return result:

                        return new ReadResult(DateTime.UtcNow)
                        {
                            WasValueRead = true,
                            ReadValue = geoLocation
                        };
                    }
                }

            }

            return new ReadResult(DateTime.UtcNow)
            {
                WasValueRead = true,
                ReadValue = String.Empty
            };
        }
    }
}
  
```

AddressFieldReaderConverter:

```
      
using Sitecore.DataExchange.DataAccess;
using Sitecore.DataExchange.Extensions;
using Sitecore.DataExchange.Repositories;
using Sitecore.Services.Core.Model;
using System;
using Sitecore.DataExchange.Converters;

namespace Example
{
    public class AddressFieldReaderConverter : BaseItemModelConverter<ItemModel, IValueReader> 
    {
        private AddressFieldReader _reader = (AddressFieldReader)null;

        private static readonly Guid TemplateId = Guid.Parse("{C3C9E93C-F197-4FBD-820D-DCB565707AF7}");
        public AddressFieldReaderConverter(IItemModelRepository repository)
      : base(repository)
        {
            this.SupportedTemplateIds.Add(TemplateId);
        }

        public override bool CanConvert(ItemModel source)
        {
            return true;
        }

        public override IValueReader Convert(ItemModel source)
        {
            if (source == null)
            {
                Sitecore.DataExchange.Context.Logger.Error("Cannot convert null item to value reader. (converter: {0})", (object)this.GetType().FullName);
                return (IValueReader)null;
            }
            if (!this.CanConvert(source))
            {
                Sitecore.DataExchange.Context.Logger.Error("Cannot convert item to value reader. (item: {0}, converter: {1})", (object)source.GetItemId(), (object)this.GetType().FullName);
                return (IValueReader)null;

            }

            if (_reader == null)
                _reader = new AddressFieldReader(ItemModelRepository);
            return (IValueReader)_reader;
        }
    }
}
  
```

You also need to implement a Value Accessor for passing the Attribute Name Value from the Value Accessor to the Field Reader:

```
      
using Sitecore.DataExchange.Converters.DataAccess.ValueAccessors;
using Sitecore.DataExchange.DataAccess;
using Sitecore.DataExchange.DataAccess.Writers;
using Sitecore.DataExchange.Providers.DynamicsCrm.DataAccess.Readers;
using Sitecore.DataExchange.Repositories;
using Sitecore.Services.Core.Model;
using System;

namespace Example
{
    public class CustomValueAccessorConverter : ValueAccessorConverter
    {
        private static readonly Guid TemplateId = Guid.Parse("{C3C9E93C-F197-4FBD-820D-DCB565707AF7}");

        public LookupValueAccessorConverter(IItemModelRepository repository)
          : base(repository)
        {
            this.SupportedTemplateIds.Add(LookupValueAccessorConverter.TemplateId);
        }

        public override IValueAccessor Convert(ItemModel source)
        {
            IValueAccessor valueAccessor = base.Convert(source);
            if (valueAccessor == null)
                return (IValueAccessor)null;

            string stringValue = this.GetStringValue(source, "AttributeName");
            if (string.IsNullOrWhiteSpace(stringValue))
                return (IValueAccessor)null;
            bool boolValue = this.GetBoolValue(source, "UseValueProperty");

            if (valueAccessor.ValueReader == null)
            {
                EntityAttributeValueReader attributeValueReader = new EntityAttributeValueReader(stringValue);
                if (this.GetBoolValue(source, "UseValueProperty"))
                    attributeValueReader.UseValueProperty = true;
                valueAccessor.ValueReader = (IValueReader)attributeValueReader;
            }
            else
            {
                //Custom part. Initialize attribute for read

                var customFieldReader = valueAccessor.ValueReader as IBaseValueReader;
                if (customFieldReader != null)
                {
                    customFieldReader.AttributeName = stringValue;
                }
            }

            if (valueAccessor.ValueWriter == null && !boolValue)
                valueAccessor.ValueWriter = (IValueWriter)new IndexerPropertyValueWriter(new object[1]
                {
          (object) stringValue
                });

            return valueAccessor;
        }
    }
}

```

Then you need to create a template for AddressField Reader and inherit it from the Value Reader template (https://www.brimit.com/sitecore/templates/Data Exchange/Framework/Data Access/Value Readers/Value Reader):

![crm connect template](https://www.brimit.com/-/media/images/blog/crmconnect1.png)

![crm connect template 2 ](https://www.brimit.com/-/media/images/blog/crmconnect2.png)

Then, based on this template, you need to create a Value Reader Item (make sure the converter is correct):

![CRM  connect Value Reader Item](https://www.brimit.com/-/media/images/blog/crmconnect3.png)

The next step is to create a Value Accessor for your import object (make sure the Converter type set to your custom implemented):

![crm connect Value Accessor](https://www.brimit.com/-/media/images/blog/crmconnect4.png)

You can use this Value Accessor in your Value Mapping Set.

After that you need to run an import and see if it is works. 

Did it work for you? [Tell us](https://www.brimit.com/contact-us "Comments on article") what you think!

###### Author

[!\[artsiom-photo\](https://www.brimit.com/-/jssmedia/feature/blogs/authors/artsiom-200.jpg?h=202&amp;iar=0&amp;w=200&amp;hash=41797D2540DF6EB6FDF558360F6F62B8)
Artsem Prashkovich
Sitecore MVP/ Solution Architect](https://www.brimit.com/blog/author?authors=Artsem%20Prashkovich)

#### More on Sitecore

[!\[How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2024/vercel_cover-image.png)
#Guides#How-toDXPE-commerce
##### How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects
Optimize and accelerate the development and deployment of complex multisite Sitecore projects.
Alexei Vershalovich on July 17, 2024](https://www.brimit.com/blog/how-vercel-will-help-you-save-effort-when-deploying-sophisticated-sitecore-projects)

[!\[Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2023/sitecore-mentoring---cover-image.png)
#How-toDXP
##### Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story
How to participate in the Sitecore Mentor program and help younger colleagues jump-start a career in Sitecore development.
Sergey Baranov on October 2, 2023](https://www.brimit.com/blog/training-up-tomorrows-sitecore-mvps)

[!\[Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2022/headless/adobestock_456986731.jpg)
#How-toDXPE-commerce
##### Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)
Discover how a headless CMS can benefit organizations that use Sitecore.
Daniil Raschupkin, Palina Trokhautsava on September 15, 2022](https://www.brimit.com/blog/going-headless-part-2-when-a-headless-cms-is-your-best-bet-if-you-have-sitecore)

![](https://bat.bing.net/action/0?ti=187017043&amp;tm=gtm002&amp;Ver=2&amp;mid=a5917390-189a-43db-be58-17eed4dd1e80&amp;bo=2&amp;gtm_tag_source=1&amp;pi=0&amp;lg=en-US&amp;sw=800&amp;sh=600&amp;sc=24&amp;nwd=1&amp;tl=Dynamics%20CRM%20Connect%3A%20Implementing%20Custom%20Field%20Reader%20and%20Value%20Accessor&amp;kw=Sitecore,%20Dynamics,%20CRM,%20Connect,%20search,%20custom,%20accessor,%20field,%20value&amp;p=https%3A%2F%2Fwww.brimit.com%2Fblog%2Fdynamics-crm-connect-custom-accessor&amp;r=&amp;lt=270&amp;evt=pageLoad&amp;sv=2&amp;asc=D&amp;cdb=AQAY&amp;rn=33095)