DLaB.Xrm.XrmToolBoxTools icon indicating copy to clipboard operation
DLaB.Xrm.XrmToolBoxTools copied to clipboard

Retrieve original option set values

Open seangwright opened this issue 8 years ago • 8 comments

Hello,

I have a generated option set used for Accounts that looks like this

[System.Runtime.Serialization.DataContractAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("CrmSvcUtil", "8.1.0.7711")]
public enum Account_IndustryCode
{
	[System.Runtime.Serialization.EnumMemberAttribute()]
	AgricultureForestryFishingMiningConstruction = 806860000,
	
	[System.Runtime.Serialization.EnumMemberAttribute()]
	CoalitionsConsortiums = 806860010,
	
	[System.Runtime.Serialization.EnumMemberAttribute()]
	Educationalproviders = 100000000,
	
	[System.Runtime.Serialization.EnumMemberAttribute()]
	FinanceInsuranceAndRealEstate = 806860003,
	...
}

While the original displayed option set values look like this example option set values

Is there a way to get those values (Coalitions/Consortiums) either through querying CRM (using CrmServiceContext, not the static generated enum) or generating the code differently using this tool?

Thanks

seangwright avatar Jan 05 '17 15:01 seangwright

I found this solution which doesn't use code generation

var raResponse = (RetrieveAttributeResponse)context.Execute(new RetrieveAttributeRequest
{
	EntityLogicalName = "account",
	LogicalName = "industrycode",
	RetrieveAsIfPublished = true
});

var paMetadata = (PicklistAttributeMetadata)raResponse.AttributeMetadata;

// Get the current options list for the retrieved attribute.
var keyValues = paMetadata.OptionSet.Options.Select(o => new { Id = o.Value ?? 0, Name = o.Label.UserLocalizedLabel.Label });

which works well enough for me.

seangwright avatar Jan 05 '17 16:01 seangwright

Your solution is the easiest way. "Coalitions/Consortiums" is not a valid C# Enum name. I could add an attribute that is the actual name of the Option set though... You could then use reflection to retrieve those string values, but that would be pretty far off from the standard CrmSvcUtil Enums, and I'm not sure I'm willing to perform that action...

daryllabar avatar Jan 05 '17 19:01 daryllabar

Yup, that's what I was thinking exactly as the only reasonable generated-code solution, which I agree is probably too much since there is an alternate solution.

The enums are really meant for programmatic assignment of a specific value whereas here I'm trying to display values to end users.

seangwright avatar Jan 05 '17 21:01 seangwright

Yep. And it's pretty easy to change the option set text value, which means the generated text values would be out of date anyway.

daryllabar avatar Jan 05 '17 23:01 daryllabar

A solution I saw in another tool was to put the Label in as an Attribute:

        public enum Address1_AddressType
        {
            ///<summary><para>Bill To</para>
            ///<para>Value = 1</para></summary>
            [Description("Bill To")]
            BillTo = 1,
            ///<summary><para>Ship To</para>
            ///<para>Value = 2</para></summary>
            [Description("Ship To")]
            ShipTo = 2,
            ///<summary><para>Primary</para>
            ///<para>Value = 3</para></summary>
            [Description("Primary")]
            Primary = 3,
            ///<summary><para>Other</para>
            ///<para>Value = 4</para></summary>
            [Description("Other")]
            Other = 4
        }

You can then retrieve the name using https://msdn.microsoft.com/en-us/library/71s1zwct(v=vs.110).aspx, although I guess a nice wrapper method around that would be nicer.

cseymr avatar Jan 09 '17 12:01 cseymr

@craigseymour do you have a use case for this? Generally, I like to operate with the understanding, that people can change the text values of Option sets without ever affecting the system. This opens the door to a label change causing errors...

daryllabar avatar Jan 09 '17 14:01 daryllabar

I don't have a strong use case - it was more a suggestion of a mechanism to address @sgwatgit's enquiry.

If I do have one is that I want to have a one-stop shop for everything I want to know about an Option Set without having to shell out to the OrganizationService. The downside, as you point out, is that the class is only a truthful representation of the Option Set at the moment it is generated.

But that applies to everything - the values, the labels, the order... So, as Option Sets are basically fragile anyway, I'm not sure that adding in the labels to the class makes it any worse :-)

As for introducing inaccuracies - My general assumption is that when the Option Set changes, I want the class to update too. If my enum name changes I want my compiler/unit tests to barf, otherwise the code might not be doing what I intended and probably doesn't read correctly anymore (depending of course what is has changed from and to!). If I'm foolish enough to use the Option Set label to apply logic, then I deserve what I get :-)

Especially when one considers localization...

cseymr avatar Jan 09 '17 14:01 cseymr

I'm going to open this up as "help wanted" if anyone wants to implement this and send me a PR, I'll take it.

daryllabar avatar Jan 09 '17 15:01 daryllabar

This was actually implemented with the Generate OptionSet Metadata option some time ago.

daryllabar avatar Apr 01 '23 17:04 daryllabar