0

The UI Editor in Dynamics CRM won't allow system admins to directly edit status/statecode picklists on the Activity Entity. How can the order be edited programatically?

In another question, information is provided about how to get metadata about statuscodes and statecodes: Dynamics Crm: Get metadata for statuscode/statecode mapping

Microsoft provides a class for sorting order of picklists: https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg327607(v%3dcrm.8)

I have successsfully coded and can retrieve metadata for both standard picklists and for statuscodes picklists (both the statecode and statuscode). I can programatically update the sort order on standard picklists, but when attempting to do so on a statuscode optionset, no errors are thrown and no changes are published to the system.

How can the sort order on the activity statuscode field be updated?

Example code follows, complete with both tests:


namespace ConsoleApps
{
    class EditAptStatusCodeOptionSetOrder
    {
        static void Main()
        {
            //Connect to Database
            string CRMConnectionString = @"AuthType = Office365; URL = https://URLOFSERVER; Username=USERNAME; Password=PASSWORD;";
            Console.WriteLine("Connecting to Auric Solar Sandbox Environment Using Ryan Perry's Credentials. ");
            CrmServiceClient crmServiceClient = new CrmServiceClient(CRMConnectionString);
            IOrganizationService crmService = crmServiceClient.OrganizationServiceProxy;

            //Test Retrieving Stage (Statuscode) from Test Entity. 
            //Get the Attribute
            RetrieveAttributeRequest retrieveStatusCodeAttributeRequest = new RetrieveAttributeRequest
            {
                EntityLogicalName = "new_testentity",
                LogicalName = "statuscode",
                RetrieveAsIfPublished = true
            };

            RetrieveAttributeResponse retrieveStatusCodeAttributeResponse =
                (RetrieveAttributeResponse)crmService.Execute(retrieveStatusCodeAttributeRequest);
            Console.WriteLine("Retreived Attribute:" +
                retrieveStatusCodeAttributeResponse.AttributeMetadata.LogicalName);
            Console.WriteLine("Retreived Attribute Description:" +
                retrieveStatusCodeAttributeResponse.AttributeMetadata.Description);

            StatusAttributeMetadata statusCodeMetaData =
                (StatusAttributeMetadata)retrieveStatusCodeAttributeResponse.AttributeMetadata;
            Console.WriteLine("Metadata Description:" +
                statusCodeMetaData.Description);
            Console.WriteLine("Metadata IsValidForUpdate:" +
                statusCodeMetaData.IsValidForUpdate.ToString());
            Console.WriteLine("OptionSet Type:" +
                statusCodeMetaData.OptionSet.Name.ToString());
            Console.WriteLine("OptionSet Name:" +
                statusCodeMetaData.OptionSet.OptionSetType.ToString());
            Console.WriteLine("Retrieved Options:");
            foreach (OptionMetadata optionMeta in statusCodeMetaData.OptionSet.Options)
            {
                Console.WriteLine(((StatusOptionMetadata)optionMeta).State.Value + " : " + optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);

            }


            //Save Options in an array to reorder.
            OptionMetadata[] optionList = statusCodeMetaData.OptionSet.Options.ToArray();
            Console.WriteLine("Option Array:");
            foreach (OptionMetadata optionMeta in optionList)
            {
                Console.WriteLine(((StatusOptionMetadata)optionMeta).State.Value + " : " + optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);
            }

            var sortedOptionList = optionList.OrderBy(x => x.Label.LocalizedLabels[0].Label).ToList();

            Console.WriteLine("Sorted Option Array:");
            foreach (OptionMetadata optionMeta in sortedOptionList)
            {
                Console.WriteLine(((StatusOptionMetadata)optionMeta).State.Value + " : " + optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);
            }


            //Create the request.
            OrderOptionRequest orderStatusCodeOptionRequest = new OrderOptionRequest
            {
                AttributeLogicalName = "statuscode",
                EntityLogicalName = "new_testentity",
                Values = sortedOptionList.Select(X => X.Value.Value).ToArray()
            };
            Console.WriteLine("orderStatusCodeOptionRequest Created.");

            //Execute Request. //////THIS DOESN'T THROW ERRORS, BUT DOESN'T UPDATE SYSTEM. 
            OrderOptionResponse orderStatusCodeResponse = (OrderOptionResponse)crmService.Execute(orderStatusCodeOptionRequest);
            Console.WriteLine("Request Executed");







            ////////////////////////////////////////PICKLIST TEST//////////////////////////////////

            Console.WriteLine("\n\nTestingPickList");
            RetrieveAttributeRequest retrieveTestPicklistAttributeRequest = new RetrieveAttributeRequest
            {
                EntityLogicalName = "new_testentity",
                LogicalName = "new_testpicklist",
                RetrieveAsIfPublished = true
            };
            RetrieveAttributeResponse retrieveTestPicklistAttributeResponse =
                (RetrieveAttributeResponse)crmService.Execute(retrieveTestPicklistAttributeRequest);
            PicklistAttributeMetadata pickListMetaData =
                (PicklistAttributeMetadata)retrieveTestPicklistAttributeResponse.AttributeMetadata;
            Console.WriteLine("Retrieved Picklist Options:");
            foreach (OptionMetadata optionMeta in pickListMetaData.OptionSet.Options)
            {
                Console.WriteLine(optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);

            }


            //Save Options in an array to reorder.
            OptionMetadata[] picklistOptionList = pickListMetaData.OptionSet.Options.ToArray();
            Console.WriteLine("Picklist Option Array:");
            foreach (OptionMetadata optionMeta in picklistOptionList)
            {
                Console.WriteLine(optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);
            }

            var sortedPicklistOptionList = picklistOptionList.OrderBy(x => x.Label.LocalizedLabels[0].Label).ToList();

            Console.WriteLine("Picklist Sorted Option Array:");
            foreach (OptionMetadata optionMeta in sortedPicklistOptionList)
            {
                Console.WriteLine(optionMeta.Value + " : " + optionMeta.Label.UserLocalizedLabel.Label);
            }

            //Create the request.
            OrderOptionRequest orderPicklistOptionRequest = new OrderOptionRequest
            {
                AttributeLogicalName = "new_testpicklist",
                EntityLogicalName = "new_testentity",
                Values = sortedPicklistOptionList.Select(X => X.Value.Value).ToArray()
            };
            Console.WriteLine("orderPicklistOptionRequest Created.");

            //Execute Request.
            OrderOptionResponse orderPicklistResponse = (OrderOptionResponse)crmService.Execute(orderPicklistOptionRequest);
            Console.WriteLine("Order Picklist Request Executed");


            //Publish All.
            Console.WriteLine("Publishing. Please Wait...");
            PublishAllXmlRequest publishRequest = new PublishAllXmlRequest();
            crmService.Execute(publishRequest);
            Console.WriteLine("Done.");

            Console.ReadLine();

        }
    }
}
  • You can sort the order but not "forever", when the form displays to the user, with javascript, you can order de optionset as you wish. – Sxntk Sep 25 '18 at 14:36
  • Hi Sxntk, This becomes an issue specifically when user closes the apt via the ribbon on an appointment record. If a user wishes to mark an apt completed, they just click "Mark Complete" directly on the ribbon, but if cancelling, they have to click "Close Appointment", then change the value in a popup box from complete to cancelled, which is a minor nuisance we are trying to fix. We'd like Cancelled to be the first, default option on this popup. ... We may be able to replace the "Close Appointment" ribbon button with a "Cancel Appointment" button. Time to learn how to edit the ribbon. – Ryan C. Perry Sep 26 '18 at 15:11

0 Answers0