PicklistAttributeMetadata
PicklistAttributeMetadata is the primary vehicle that allows you to retrieve information about Microsoft Dynamics CRM 2011 (MSCRM) Picklist values. Every notable Picklist property that you’d need to interact with is available using it. And fortunately, it’s quite simple to use.
A common scenario you run into is creating a form or control in ASP.NET / Silverlight that mimics the behavior of an actual MSCRM form. So let’s say that one of the attributes you need to simulate is a Picklist. You have two options. The quick and dirty (and lame) approach is to hard code both the label and values for each item. If your app is used in multiple locales that happen to use different languages, then you have to not only populate the control using the primary language, but you’d need to make sure it’s populated correctly using each of localized values as well. This is first and foremost lame. It’s error prone b/c you have to ensure that you match each value in each respect or there will be a mismatch when you attempt to use values you retrieved from the control or form. You’d also be very vulnerable to changes in environments (where the values are different) or changes made after deployment. It also means you’d be duplicating effort, not just now but in the future any time values changed. Additionally, it would be very easy for someone to make a change to the existing picklist and without realizing it, break any app that was dependent on matching values. I’ll leave it at this, hard coding is pretty much always a bad idea and in this case, it’s extremely bad for many reasons.
If you aren’t familiar with them already, please take a quick look at using the CrmConnection (Microsoft.Xrm.Client.CrmConnection ) and IOrganizationService / OrganizationService (Microsoft.Xrm.Client.Services.OrganizationService) as refresher as the OrganizationService is the basis of all of the api interaction I’ll be discussing. So start out by instantiating a new instance of the CrmConnection, then instantiating a new OrganizationService instance, passing in the CrmConnection you just created to the OrganizaitonService ‘s constructor.
CrmConnection ConnectionInstance = new CrmConnection("MSCRM"); IOrganizationService ServiceInstance = new OrganizationService(ConnectionInstance);
So the first step you’ll take after creating the CrmConnection and OrganizationService is to create a new RetrieveAttributeRequest (Microsoft.Xrm.Sdk.Messages.RetrieveAttributeRequest). If you have multiple Picklist s that you want to simulate, I’d recommend making this a function and using parameters so that the code is repeatable, but that’s an app specific design consideration that is not really relevant to this discussion.
RetrieveAttributeRequest NewAttributeRequest = new RetrieveAttributeRequest { EntityLogicalName = "contact", LogicalName = "shippingprovider", RetrieveAsIfPublished = true };
Creating a new RetrieveAttributeRequest is pretty much as simple as it looks. The only thing to keep in mind is that the EntityLogicalName is the name of the Entity containing the specific attribute defined as a Picklist. The RetrieveAttributeRequest.LogicalName is the name of the specific attribute. The RetrieveAttributeRequest.RetrieveAsIfPublished property does exactly what you’d expect it to – if the modifications to the picklist have been published, they’ll be returned if the RetrieveAsIfPublished is set to true and it’ll ignore than if RetrieveAsIfPublished is set to false.
With the RetrieveAttributeRequest created, you simply need to pass it to the Execute method of the OrganizationService you defined. To do much with it though, you’ll need to follow the Request/Response design pattern used throughout the MSCRM 2011 SDK and capture the return information with a RetrieveAttributeResponse (Microsoft.Xrm.Sdk.Messages.RetrieveAttributeResponse) item:
RetrieveAttributeResponse PicklistResponse = (ServiceInstance.Execute(NewAttributeRequest) as RetrieveAttributeResponse);
Although not necessary, I recommend using the as operator to perform the case and then checking whether or not the value is null to see if it was successful (all caveats about exception handling and logging are obviously in place here). Once you confirm the RetrieveAttributeRequest call was successful, you can use the several properties of the RetrieveAttributeResponse to interact with the metadata.
The RetrieveAttributeResponse has several useful properties that you’ll want to take advantage of. One of the more useful ones is called unsurprisingly, RetrieveAttributeResponse.AttributeMetadata.
if (null != PicklistResponse) { PicklistAttributeMetadata PicklistMetaDetails = (PicklistResponse.AttributeMetadata as PicklistAttributeMetadata); if (null != PicklistMetaDetails) { ... } }
Once you’ve verified the existence of the RetrieveAttributeResponse, you simply reference the AttributeMetadata (which also entails another cast operation, which I’d similarly recommend using the As operator to perform).
The PicklistAttributeMetadata contains several pieces of important information that you’ll want to interact with and in this case, you’d want to reference the OptionSet property (PicklistAttributeMetadata.OptionSet ). Each item in the OptionSet is held in the Options collection which has a ToArray (non-generic) implementation out of the box. Once you’ve referenced this, there are several pieces of pertinent data exposed as properties which you can use to customize the behavior of your new page or controls.
Each of the Option values are typed as OptionMetadata (Microsoft.Xrm.Sdk.Metadata.OptionMetadata) items. These properties include the Label property, and Value property among others, but these two are the ones you’ll likely be using most. The Label and Value properties work just like you’d expect them to, the Label is the text defined to be shown in the Picklist, the Value is the integer value that it represents. However there’s one thing worth noting. If you only have your labels defined in one language, and are 100% sure that you’ll never ever have another language defined, there’s little risk to referencing the Label property as it stands. But in most cases, you either will have multi-language support or won’t be so sure of the future, so it’s safer to use the Label.UserLocalizedLabel property which provides the text that’s actually localized to the specific user. Using the UserLocalizedLabel however does mean that youll need to be cognizant of the user context the operations are being performed as but that’s going to be the case for many other reasons outside of this. Plugins or Workflows will already have this awareness factored in so it’ll only be a concern if you’re using a generalized account that needs to be aware of different locales. The relevant pieces are shown below:
if (null != PicklistResponse) { PicklistAttributeMetadata PicklistMetaDetails = (PicklistResponse.AttributeMetadata as PicklistAttributeMetadata); if (null != PicklistMetaDetails) { OptionMetadata[] OptionsList = PicklistMetaDetails.OptionSet.Options.ToArray(); if (null != OptionsList && OptionsList.Length > 0) { // Bind to control, iterate, do with what you will here // using OptionMetadata.Label or // OptionMetadata.Label.UserLocalizedLabel.Label // OptionMetadata.Value etc. } } }
The fully assembled code is shown below:
CrmConnection ConnectionInstance = new CrmConnection("MSCRM"); IOrganizationService ServiceInstance = new OrganizationService(ConnectionInstance); RetrieveAttributeRequest NewAttributeRequest = new RetrieveAttributeRequest { EntityLogicalName = "contact", LogicalName = "shippingprovider", RetrieveAsIfPublished = true }; RetrieveAttributeResponse PicklistResponse = (ServiceInstance.Execute(NewAttributeRequest) as RetrieveAttributeResponse); if (null != PicklistResponse) { PicklistAttributeMetadata PicklistMetaDetails = (PicklistResponse.AttributeMetadata as PicklistAttributeMetadata); if (null != PicklistMetaDetails) { OptionMetadata[] OptionsList = PicklistMetaDetails.OptionSet.Options.ToArray(); if (null != OptionsList && OptionsList.Length > 0) { // Bind to control, iterate, do with what you will here // using OptionMetadata.Label or // OptionMetadata.Label.UserLocalizedLabel.Label // OptionMetadata.Value etc. } } }
————————————————————–
KeyWords: Dynamics4, Dynamics4,com, MSCRM 2011, Microsoft Dynamics CRM 2011, CrmConnection 2011, OrganizationService, RetrieveAttributeRequest, RetrieveAttributeResponse, PicklistAttributeMetadata, OptionSet, OptionMetadata,
—
Do you have an example of how this can be done client side?