Trevor Daniel
Trevor Daniel

Reputation: 3974

Dynamics CRM - Accessing Custom Product Option Value

Is there a way to programmatically access the Label & Value fields that has been created as a custom Field in MS CRM Dynamics please?

I have added a custom field called "new_producttypesubcode" which, for example, has 2 options, Trophy = 1000000 and Kit = 10000001.

I am writing an import utility that mirrors products between the customers website and their CRM and I want to get a list of all possible product options in the CRM to see if they are matched in the website.

So, in essence I want to...

  1. get the list of possible new_producttypesubcodes and their corresponding values.
  2. Iterate through the product variants in the website.
  3. if the product variant name matches any name in the list of new_producttypecodes then add the value 1000000

So, if I find a product added to the website and its marked as a "Trophy" and "Trophy" exists in the CRM then new OptionSetValue(100000001)

I hope that makes sense...

Thanks

Upvotes: 2

Views: 3918

Answers (2)

James Wood
James Wood

Reputation: 17562

This function retrieves a dictionary of possible values localised to the current user. Taken from: CRM 2011 Programatically Finding the Values of Picklists, Optionsets, Statecode, Statuscode and Boolean (Two Options).

static Dictionary<String, int> GetNumericValues(IOrganizationService service, String entity, String attribute)
{
    RetrieveAttributeRequest request = new RetrieveAttributeRequest
    {
        EntityLogicalName = entity,
        LogicalName = attribute,
        RetrieveAsIfPublished = true
    };

    RetrieveAttributeResponse response = (RetrieveAttributeResponse)service.Execute(request);

    switch (response.AttributeMetadata.AttributeType)
    {
        case AttributeTypeCode.Picklist:
        case AttributeTypeCode.State:
        case AttributeTypeCode.Status:
            return ((EnumAttributeMetadata)response.AttributeMetadata).OptionSet.Options
                .ToDictionary(key => key.Label.UserLocalizedLabel.Label, option => option.Value.Value);

        case AttributeTypeCode.Boolean:
            Dictionary<String, int> values = new Dictionary<String, int>();

            BooleanOptionSetMetadata metaData = ((BooleanAttributeMetadata)response.AttributeMetadata).OptionSet;

            values[metaData.TrueOption.Label.UserLocalizedLabel.Label] = metaData.TrueOption.Value.Value;
            values[metaData.FalseOption.Label.UserLocalizedLabel.Label] = metaData.FalseOption.Value.Value;

            return values;

        default:
            throw new ArgumentOutOfRangeException();
    }
}

So you would then need to do something like:

Dictionary<String, int> values = GetNumericValues(proxy, "your_entity", "new_producttypesubcode");

if(values.ContainsKey("Trophy"))
{
    //Do something with the value
    OptionSetValue optionSetValue = values["Trophy"];
    int value = optionSetValue.Value;
}

Upvotes: 5

Andy Meyers
Andy Meyers

Reputation: 1581

Yes, that data is all stored in the metadata for an attribute (SDK article). You have to retrieve the entity metadata for the entity and then find the attribute in the list. Then cast that attribute to a PicklistAttributeMetadata object and it will contain a list of options. I would mention that typically retrieving Metadata from CRM is an expensive operation, so think about caching.

private static OptionSetMetadata RetrieveOptionSet(IOrganizationService orgService,
    string entityName, string attributeName)
{
    var entityResponse = (RetrieveEntityResponse)orgService.Execute(
        new RetrieveEntityRequest 
            { LogicalName = entityName, EntityFilters = EntityFilters.Attributes });

    var entityMetadata = entityResponse.EntityMetadata;

    for (int i = 0; i < entityMetadata.Attributes.Length; i++)
    {
        if (attributeName.Equals(entityMetadata.Attributes[i].LogicalName))
        {
            if (entityMetadata.Attributes[i].AttributeType.Value == 
                    AttributeTypeCode.Picklist)
            {
                var attributeMD = (PicklistAttributeMetadata)
                    entityMetadata.Attributes[i];

                return attributeMD.OptionSet;
            }
        }
    }

    return null;
}

Here is how to write the options to the console using the above call.

var optionSetMD = RetrieveOptionSet(orgService, "account", "accountcategorycode");
var options = optionSetMD.Options;

for (int i = 0; i < options.Count; i++)
{
    Console.WriteLine("Local Label: {0}.  Value: {1}",
        options[i].Label.UserLocalizedLabel.Label,
        options[i].Value.HasValue ? options[i].Value.Value.ToString() : "null");
}

I believe this works for global option set attributes as well, but if you know it is a global option set there is a different message for it that would probably a bit more efficient (SDK article).

Upvotes: 2

Related Questions