Share via


Sample: Work with attributes

 

Applies To: Dynamics CRM 2013

This sample code is for Microsoft Dynamics CRM 2013 and Microsoft Dynamics CRM Online. Download the Microsoft Dynamics CRM SDK package. It can be found in the following location in the download package:

SampleCode\CS\Metadata\Attributes\WorkWithAttributes.cs

SampleCode\VB\Metadata\Attributes\WorkWithAttributes.vb

Requirements

For more information about the requirements for running the sample code provided in this SDK, see Use the sample and helper code.

Demonstrates

This sample shows how to perform various actions on attributes.

Example


using System;
using System.Linq;
using System.Xml.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Collections.Generic;

// These namespaces are found in the Microsoft.Xrm.Sdk.dll assembly
// found in the SDK\bin folder.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;

// This namespace is found in Microsoft.Crm.Sdk.Proxy.dll assembly
// found in the SDK\bin folder.
using Microsoft.Crm.Sdk.Messages;

namespace Microsoft.Crm.Sdk.Samples
{
    /// <summary>
    /// This sample shows how to create, retrieve, update and delete attribute.
    /// </summary>
    public class WorkWithAttributes
    {
        #region Class Level Members

        /// <summary>
        /// Stores the organization service proxy.
        /// </summary>
        OrganizationServiceProxy _serviceProxy;

        // Create storage for new attributes being created
        public List<AttributeMetadata> addedAttributes;

        // Specify which language code to use in the sample. If you are using a language
        // other than US English, you will need to modify this value accordingly.
        // See https://msdn.microsoft.com/en-us/library/0h88fahh.aspx
        public const int _languageCode = 1033;

        // Define the IDs/variables needed for this sample.
        public int _insertedStatusValue;

        #endregion Class Level Members

        #region How To Sample Code
        /// <summary>
        /// Create and configure the organization service proxy.
        /// Create few types of attributes.
        /// Insert status in the existing status list.
        /// Retrieve attribute.
        /// Update attribute.
        /// Update existing state value.
        /// Optionally delete/revert any attributes 
        /// that were created/changed for this sample.
         /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptForDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig, bool promptForDelete)
        {
            try
            {

                // Connect to the Organization service. 
                // The using statement assures that the service proxy will be properly disposed.
                using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
                {
                    // This statement is required to enable early-bound type support.
                    _serviceProxy.EnableProxyTypes();

                    #region How to create attributes
                    // Create storage for new attributes being created
                    addedAttributes = new List<AttributeMetadata>();

                    // Create a boolean attribute
                    BooleanAttributeMetadata boolAttribute = new BooleanAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_boolean",
                        DisplayName = new Label("Sample Boolean", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Boolean Attribute", _languageCode),
                        // Set extended properties
                        OptionSet = new BooleanOptionSetMetadata(
                            new OptionMetadata(new Label("True", _languageCode), 1),
                            new OptionMetadata(new Label("False", _languageCode), 0)
                            )
                    };

                    // Add to list
                    addedAttributes.Add(boolAttribute);

                    // Create a date time attribute
                    DateTimeAttributeMetadata dtAttribute = new DateTimeAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_datetime",
                        DisplayName = new Label("Sample DateTime", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("DateTime Attribute", _languageCode),
                        // Set extended properties
                        Format = DateTimeFormat.DateOnly,
                        ImeMode = ImeMode.Disabled
                    };

                    // Add to list
                    addedAttributes.Add(dtAttribute);

                    // Create a decimal attribute   
                    DecimalAttributeMetadata decimalAttribute = new DecimalAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_decimal",
                        DisplayName = new Label("Sample Decimal", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Decimal Attribute", _languageCode),
                        // Set extended properties
                        MaxValue = 100,
                        MinValue = 0,
                        Precision = 1
                    };

                    // Add to list
                    addedAttributes.Add(decimalAttribute);

                    // Create a integer attribute   
                    IntegerAttributeMetadata integerAttribute = new IntegerAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_integer",
                        DisplayName = new Label("Sample Integer", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Integer Attribute", _languageCode),
                        // Set extended properties
                        Format = IntegerFormat.None,
                        MaxValue = 100,
                        MinValue = 0
                    };

                    // Add to list
                    addedAttributes.Add(integerAttribute);

                    // Create a memo attribute 
                    MemoAttributeMetadata memoAttribute = new MemoAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_memo",
                        DisplayName = new Label("Sample Memo", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Memo Attribute", _languageCode),
                        // Set extended properties
                        Format = StringFormat.TextArea,
                        ImeMode = ImeMode.Disabled,
                        MaxLength = 500
                    };

                    // Add to list
                    addedAttributes.Add(memoAttribute);

                    // Create a money attribute 
                    MoneyAttributeMetadata moneyAttribute = new MoneyAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_money",
                        DisplayName = new Label("Money Picklist", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Money Attribue", _languageCode),
                        // Set extended properties
                        MaxValue = 1000.00,
                        MinValue = 0.00,
                        Precision = 1,
                        PrecisionSource = 1,
                        ImeMode = ImeMode.Disabled
                    };

                    // Add to list
                    addedAttributes.Add(moneyAttribute);

                    // Create a picklist attribute  
                    PicklistAttributeMetadata pickListAttribute =
                        new PicklistAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_picklist",
                        DisplayName = new Label("Sample Picklist", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("Picklist Attribute", _languageCode),
                        // Set extended properties
                        // Build local picklist options
                        OptionSet = new OptionSetMetadata
                            {
                                IsGlobal = false,
                                OptionSetType = OptionSetType.Picklist,
                                Options = 
                            {
                                new OptionMetadata(
                                    new Label("Created", _languageCode), null),
                                new OptionMetadata(
                                    new Label("Updated", _languageCode), null),
                                new OptionMetadata(
                                    new Label("Deleted", _languageCode), null)
                            }
                            }
                    };

                    // Add to list
                    addedAttributes.Add(pickListAttribute);

                    // Create a string attribute
                    StringAttributeMetadata stringAttribute = new StringAttributeMetadata
                    {
                        // Set base properties
                        SchemaName = "new_string",
                        DisplayName = new Label("Sample String", _languageCode),
                        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
                        Description = new Label("String Attribute", _languageCode),
                        // Set extended properties
                        MaxLength = 100
                    };

                    // Add to list
                    addedAttributes.Add(stringAttribute);

                    // NOTE: LookupAttributeMetadata cannot be created outside the context of a relationship.
                    // Refer to the WorkWithRelationships.cs reference SDK sample for an example of this attribute type.

                    // NOTE: StateAttributeMetadata and StatusAttributeMetadata cannot be created via the SDK.

                    foreach (AttributeMetadata anAttribute in addedAttributes)
                    {
                        // Create the request.
                        CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
                        {
                            EntityName = Contact.EntityLogicalName,
                            Attribute = anAttribute
                        };

                        // Execute the request.
                        _serviceProxy.Execute(createAttributeRequest);

                        Console.WriteLine("Created the attribute {0}.", anAttribute.SchemaName);
                    }
                    #endregion How to create attributes

                    #region How to insert status
                    // Use InsertStatusValueRequest message to insert a new status 
                    // in an existing status attribute. 
                    // Create the request.
                    InsertStatusValueRequest insertStatusValueRequest =
                        new InsertStatusValueRequest
                    {
                        AttributeLogicalName = "statuscode",
                        EntityLogicalName = Contact.EntityLogicalName,
                        Label = new Label("Dormant", _languageCode),
                        StateCode = 0
                    };

                    // Execute the request and store newly inserted value 
                    // for cleanup, used later part of this sample. 
                    _insertedStatusValue = ((InsertStatusValueResponse)_serviceProxy.Execute(
                        insertStatusValueRequest)).NewOptionValue;

                    Console.WriteLine("Created {0} with the value of {1}.",
                        insertStatusValueRequest.Label.LocalizedLabels[0].Label,
                        _insertedStatusValue);
                    #endregion How to insert status

                    #region How to retrieve attribute
                    // Create the request
                    RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest
                    {
                        EntityLogicalName = Contact.EntityLogicalName,
                        LogicalName = "new_string",
                        RetrieveAsIfPublished = true
                    };

                    // Execute the request
                    RetrieveAttributeResponse attributeResponse =
                        (RetrieveAttributeResponse)_serviceProxy.Execute(attributeRequest);

                    Console.WriteLine("Retrieved the attribute {0}.",
                        attributeResponse.AttributeMetadata.SchemaName);
                    #endregion How to retrieve attribute

                    #region How to update attribute
                    // Modify the retrieved attribute
                    AttributeMetadata retrievedAttributeMetadata =
                        attributeResponse.AttributeMetadata;
                    retrievedAttributeMetadata.DisplayName =
                        new Label("Update String Attribute", _languageCode);

                    // Update an attribute retrieved via RetrieveAttributeRequest
                    UpdateAttributeRequest updateRequest = new UpdateAttributeRequest
                    {
                        Attribute = retrievedAttributeMetadata,
                        EntityName = Contact.EntityLogicalName,
                        MergeLabels = false
                    };

                    // Execute the request
                    _serviceProxy.Execute(updateRequest);

                    Console.WriteLine("Updated the attribute {0}.",
                        retrievedAttributeMetadata.SchemaName);
                    #endregion How to update attribute

                    #region How to update state value
                    // Modify the state value label from Active to Open.
                    // Create the request.
                    UpdateStateValueRequest updateStateValue = new UpdateStateValueRequest
                    {
                        AttributeLogicalName = "statecode",
                        EntityLogicalName = Contact.EntityLogicalName,
                        Value = 1,
                        Label = new Label("Open", _languageCode)
                    };

                    // Execute the request.
                    _serviceProxy.Execute(updateStateValue);

                    Console.WriteLine(
                        "Updated {0} state attribute of {1} entity from 'Active' to '{2}'.",
                        updateStateValue.AttributeLogicalName,
                        updateStateValue.EntityLogicalName,
                        updateStateValue.Label.LocalizedLabels[0].Label
                        );
                    #endregion How to update state value

                    #region How to insert a new option item in a local option set
                    // Create a request.
                    InsertOptionValueRequest insertOptionValueRequest =
                        new InsertOptionValueRequest
                    {
                        AttributeLogicalName = "new_picklist",
                        EntityLogicalName = Contact.EntityLogicalName,
                        Label = new Label("New Picklist Label", _languageCode)
                    };

                    // Execute the request.
                    int insertOptionValue = ((InsertOptionValueResponse)_serviceProxy.Execute(
                        insertOptionValueRequest)).NewOptionValue;

                    Console.WriteLine("Created {0} with the value of {1}.",
                        insertOptionValueRequest.Label.LocalizedLabels[0].Label,
                        insertOptionValue);
                    #endregion How to insert a new option item in a local option set

                    #region How to change the order of options of a local option set
                    // Use the RetrieveAttributeRequest message to retrieve  
                    // a attribute by it's logical name.
                    RetrieveAttributeRequest retrieveAttributeRequest =
                        new RetrieveAttributeRequest
                    {
                        EntityLogicalName = Contact.EntityLogicalName,
                        LogicalName = "new_picklist",
                        RetrieveAsIfPublished = true
                    };

                    // Execute the request.
                    RetrieveAttributeResponse retrieveAttributeResponse =
                        (RetrieveAttributeResponse)_serviceProxy.Execute(
                        retrieveAttributeRequest);

                    // Access the retrieved attribute.
                    PicklistAttributeMetadata retrievedPicklistAttributeMetadata =
                        (PicklistAttributeMetadata)
                        retrieveAttributeResponse.AttributeMetadata;

                    // Get the current options list for the retrieved attribute.
                    OptionMetadata[] optionList =
                        retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();

                    // Change the order of the original option's list.
                    // Use the OrderBy (OrderByDescending) linq function to sort options in  
                    // ascending (descending) order according to label text.
                    // For ascending order use this:
                    var updateOptionList =
                        optionList.OrderBy(x => x.Label.LocalizedLabels[0].Label).ToList();

                    // For descending order use this:
                    // var updateOptionList =
                    //      optionList.OrderByDescending(
                    //      x => x.Label.LocalizedLabels[0].Label).ToList();

                    // Create the request.
                    OrderOptionRequest orderOptionRequest = new OrderOptionRequest
                    {
                        // Set the properties for the request.
                        AttributeLogicalName = "new_picklist",
                        EntityLogicalName = Contact.EntityLogicalName,
                        // Set the changed order using Select linq function 
                        // to get only values in an array from the changed option list.
                        Values = updateOptionList.Select(x => x.Value.Value).ToArray()
                    };

                    // Execute the request
                    _serviceProxy.Execute(orderOptionRequest);

                    Console.WriteLine("Option Set option order changed");
                    #endregion How to change the order of options of a global option set

                    // NOTE: All customizations must be published before they can be used.
                    _serviceProxy.Execute(new PublishAllXmlRequest());
                    Console.WriteLine("Published all customizations.");

                    DeleteRequiredRecords(promptForDelete);
                }
            }

            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
        }

        /// <summary>
        /// Deletes/Reverts the record that was created/changed for this sample.
        /// <param name="prompt">Indicates whether to prompt the user to delete 
        /// the records created in this sample.</param>
        /// </summary>
        public void DeleteRequiredRecords(bool prompt)
        {
            bool deleteRecords = true;

            if (prompt)
            {
                Console.WriteLine(
                    "\nDo you want these entity records to be deleted? (y/n)");
                String answer = Console.ReadLine();

                deleteRecords = (answer.StartsWith("y") || answer.StartsWith("Y"));
            }

            if (deleteRecords)
            {
                #region How to delete attribute
                // Delete all attributes created for this sample.
                foreach (AttributeMetadata anAttribute in addedAttributes)
                {
                    // Create the request object
                    DeleteAttributeRequest deleteAttribute = new DeleteAttributeRequest
                    {
                        // Set the request properties 
                        EntityLogicalName = Contact.EntityLogicalName,
                        LogicalName = anAttribute.SchemaName
                    };
                    // Execute the request
                    _serviceProxy.Execute(deleteAttribute);
                }
                #endregion How to delete attribute

                #region How to remove inserted status value
                // Delete the newly inserted status value.
                // Create the request object
                DeleteOptionValueRequest deleteRequest = new DeleteOptionValueRequest
                {
                    AttributeLogicalName = "statuscode",
                    EntityLogicalName = Contact.EntityLogicalName,
                    Value = _insertedStatusValue
                };

                // Execute the request
                _serviceProxy.Execute(deleteRequest);

                Console.WriteLine("Deleted all attributes created for this sample.");
                #endregion How to remove inserted status value

                #region Revert the changed state value
                // Revert the state value label from Open to Active.
                // Create the request.
                UpdateStateValueRequest revertStateValue = new UpdateStateValueRequest
                {
                    AttributeLogicalName = "statecode",
                    EntityLogicalName = Contact.EntityLogicalName,
                    Value = 1,
                    Label = new Label("Active", _languageCode)
                };

                // Execute the request.
                _serviceProxy.Execute(revertStateValue);

                // NOTE: All customizations must be published before they can be used.
                _serviceProxy.Execute(new PublishAllXmlRequest());

                Console.WriteLine(
                    "Reverted {0} state attribute of {1} entity from 'Open' to '{2}'.",
                    revertStateValue.AttributeLogicalName,
                    revertStateValue.EntityLogicalName,
                    revertStateValue.Label.LocalizedLabels[0].Label
                    );
                #endregion Revert the changed state value
            }
        }
        #endregion How To Sample Code

        #region Main
        /// <summary>
        /// Standard Main() method used by most SDK samples.
        /// </summary>
        /// <param name="args"></param>
        static public void Main(string[] args)
        {
            try
            {
                // Obtain the target organization's Web address and client logon 
                // credentials from the user.
                ServerConnection serverConnect = new ServerConnection();
                ServerConnection.Configuration config = serverConnect.GetServerConfiguration();

                WorkWithAttributes app = new WorkWithAttributes();
                app.Run(config, true);
            }
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Timestamp: {0}", ex.Detail.Timestamp);
                Console.WriteLine("Code: {0}", ex.Detail.ErrorCode);
                Console.WriteLine("Message: {0}", ex.Detail.Message);
                Console.WriteLine("Plugin Trace: {0}", ex.Detail.TraceText);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
            }
            catch (System.TimeoutException ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Message: {0}", ex.Message);
                Console.WriteLine("Stack Trace: {0}", ex.StackTrace);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.InnerException.Message ? "No Inner Fault" : ex.InnerException.Message);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine(ex.Message);

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> fe
                        = ex.InnerException
                        as FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>;
                    if (fe != null)
                    {
                        Console.WriteLine("Timestamp: {0}", fe.Detail.Timestamp);
                        Console.WriteLine("Code: {0}", fe.Detail.ErrorCode);
                        Console.WriteLine("Message: {0}", fe.Detail.Message);
                        Console.WriteLine("Plugin Trace: {0}", fe.Detail.TraceText);
                        Console.WriteLine("Inner Fault: {0}",
                            null == fe.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
                    }
                }
            }
            // Additional exceptions to catch: SecurityTokenValidationException, ExpiredSecurityTokenException,
            // SecurityAccessDeniedException, MessageSecurityException, and SecurityNegotiationException.

            finally
            {

                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }

        }
        #endregion Main

    }
}

Imports System.ServiceModel
Imports System.ServiceModel.Description

' These namespaces are found in the Microsoft.Xrm.Sdk.dll assembly
' found in the SDK\bin folder.
Imports Microsoft.Xrm.Sdk
Imports Microsoft.Xrm.Sdk.Query
Imports Microsoft.Xrm.Sdk.Metadata
Imports Microsoft.Xrm.Sdk.Client
Imports Microsoft.Xrm.Sdk.Messages

' This namespace is found in Microsoft.Crm.Sdk.Proxy.dll assembly
' found in the SDK\bin folder.
Imports Microsoft.Crm.Sdk.Messages

Namespace Microsoft.Crm.Sdk.Samples
 ''' <summary>
 ''' This sample shows how to create, retrieve, update and delete attribute.
 ''' </summary>
 Public Class WorkWithAttributes
#Region "Class Level Members"

  ''' <summary>
  ''' Stores the organization service proxy.
  ''' </summary>
  Private _serviceProxy As OrganizationServiceProxy

  ' Create storage for new attributes being created
  Public addedAttributes As List(Of AttributeMetadata)

  ' Specify which language code to use in the sample. If you are using a language
  ' other than US English, you will need to modify this value accordingly.
  ' See https://msdn.microsoft.com/en-us/library/0h88fahh.aspx
  Public Const _languageCode As Integer = 1033

  ' Define the IDs/variables needed for this sample.
  Public _insertedStatusValue As Integer

#End Region ' Class Level Members

#Region "How To Sample Code"
  ''' <summary>
  ''' Create and configure the organization service proxy.
  ''' Create few types of attributes.
  ''' Insert status in the existing status list.
  ''' Retrieve attribute.
  ''' Update attribute.
  ''' Update existing state value.
  ''' Optionally delete/revert any attributes 
  ''' that were created/changed for this sample.
  ''' </summary>
  ''' <param name="serverConfig">Contains server connection information.</param>
  ''' <param name="promptForDelete">When True, the user will be prompted to delete all
  ''' created entities.</param>
  Public Sub Run(ByVal serverConfig As ServerConnection.Configuration, ByVal promptForDelete As Boolean)
   Try

    ' Connect to the Organization service. 
    ' The using statement assures that the service proxy will be properly disposed.
                _serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig)
    Using _serviceProxy
     ' This statement is required to enable early-bound type support.
                    _serviceProxy.EnableProxyTypes()

     '                    #Region "How to create attributes"
     ' Create storage for new attributes being created
     addedAttributes = New List(Of AttributeMetadata)()

     ' Create a boolean attribute
     Dim boolAttribute As BooleanAttributeMetadata = New BooleanAttributeMetadata With {
      .SchemaName = "new_boolean",
      .DisplayName = New Label("Sample Boolean", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Boolean Attribute", _languageCode),
      .OptionSet = New BooleanOptionSetMetadata(
       New OptionMetadata(
        New Label("True", _languageCode), 1),
        New OptionMetadata(
        New Label("False", _languageCode), 0)
       )
     }
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(boolAttribute)

     ' Create a date time attribute
     Dim dtAttribute As DateTimeAttributeMetadata = New DateTimeAttributeMetadata With {
      .SchemaName = "new_datetime",
      .DisplayName = New Label("Sample DateTime", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("DateTime Attribute", _languageCode),
      .Format = DateTimeFormat.DateOnly,
      .ImeMode = ImeMode.Disabled}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(dtAttribute)

     ' Create a decimal attribute    
     Dim decimalAttribute As DecimalAttributeMetadata = New DecimalAttributeMetadata With {
      .SchemaName = "new_decimal",
      .DisplayName = New Label("Sample Decimal", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Decimal Attribute", _languageCode),
      .MaxValue = 100,
      .MinValue = 0,
      .Precision = 1}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(decimalAttribute)

     ' Create a integer attribute    
     Dim integerAttribute As IntegerAttributeMetadata = New IntegerAttributeMetadata With {
      .SchemaName = "new_integer",
      .DisplayName = New Label("Sample Integer", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Integer Attribute", _languageCode),
      .Format = IntegerFormat.None,
      .MaxValue = 100,
      .MinValue = 0}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(integerAttribute)

     ' Create a memo attribute 
     Dim memoAttribute As MemoAttributeMetadata = New MemoAttributeMetadata With {
      .SchemaName = "new_memo",
      .DisplayName = New Label("Sample Memo", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Memo Attribute", _languageCode),
      .Format = StringFormat.TextArea,
      .ImeMode = ImeMode.Disabled,
      .MaxLength = 500}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(memoAttribute)

     ' Create a money attribute    
     Dim moneyAttribute As MoneyAttributeMetadata = New MoneyAttributeMetadata With {
      .SchemaName = "new_money",
      .DisplayName = New Label("Money Picklist", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Money Attribue", _languageCode),
      .MaxValue = 1000.0,
      .MinValue = 0.0,
      .Precision = 1,
      .PrecisionSource = 1,
      .ImeMode = ImeMode.Disabled}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(moneyAttribute)

     ' Create a picklist attribute    
     Dim pickListAttribute As PicklistAttributeMetadata = New PicklistAttributeMetadata With {
      .SchemaName = "new_picklist",
      .DisplayName = New Label("Sample Picklist", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("Picklist Attribute", _languageCode)}
     Dim pickListOptionSetMetadata As OptionSetMetadata = New OptionSetMetadata() With {
      .IsGlobal = False,
      .OptionSetType = OptionSetType.Picklist}
     pickListOptionSetMetadata.Options.Add(New OptionMetadata(New Label("Created", _languageCode), Nothing))
     pickListOptionSetMetadata.Options.Add(New OptionMetadata(New Label("Updated", _languageCode), Nothing))
     pickListOptionSetMetadata.Options.Add(New OptionMetadata(New Label("Deleted", _languageCode), Nothing))
     pickListAttribute.OptionSet = pickListOptionSetMetadata
     ' Set base properties
     ' Set extended properties
     ' Build local picklist options

     ' Add to list
     addedAttributes.Add(pickListAttribute)

     ' Create a string attribute
     Dim stringAttribute As StringAttributeMetadata = New StringAttributeMetadata With {
      .SchemaName = "new_string",
      .DisplayName = New Label("Sample String", _languageCode),
      .RequiredLevel = New AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
      .Description = New Label("String Attribute", _languageCode),
      .MaxLength = 100}
     ' Set base properties
     ' Set extended properties

     ' Add to list
     addedAttributes.Add(stringAttribute)

     ' NOTE: LookupAttributeMetadata cannot be created outside the context of a relationship.
     ' Refer to the WorkWithRelationships.cs reference SDK sample for an example of this attribute type.

     ' NOTE: StateAttributeMetadata and StatusAttributeMetadata cannot be created via the SDK.

     For Each anAttribute As AttributeMetadata In addedAttributes
      ' Create the request.
      Dim createAttributeRequest As CreateAttributeRequest = New CreateAttributeRequest With {
       .EntityName = Contact.EntityLogicalName,
       .Attribute = anAttribute}

      ' Execute the request.
      _serviceProxy.Execute(createAttributeRequest)

      Console.WriteLine("Created the attribute {0}.", anAttribute.SchemaName)
     Next anAttribute
     '                    #End Region ' How to create attributes

     '                    #Region "How to insert status"
     ' Use InsertStatusValueRequest message to insert a new status 
     ' in an existing status attribute. 
     ' Create the request.
     Dim insertStatusValueRequest As InsertStatusValueRequest = New InsertStatusValueRequest With {
      .AttributeLogicalName = "statuscode",
      .EntityLogicalName = Contact.EntityLogicalName,
      .Label = New Label("Dormant", _languageCode),
      .StateCode = 0}

     ' Execute the request and store newly inserted value 
     ' for cleanup, used later part of this sample. 
     _insertedStatusValue = (CType(_serviceProxy.Execute(insertStatusValueRequest), InsertStatusValueResponse)).NewOptionValue

     Console.WriteLine("Created {0} with the value of {1}.", insertStatusValueRequest.Label.LocalizedLabels(0).Label, _insertedStatusValue)
     '                    #End Region ' How to insert status

     '                    #Region "How to retrieve attribute"
     ' Create the request
     Dim attributeRequest As RetrieveAttributeRequest = New RetrieveAttributeRequest With {
      .EntityLogicalName = Contact.EntityLogicalName,
      .LogicalName = "new_string",
      .RetrieveAsIfPublished = True}

     ' Execute the request
     Dim attributeResponse As RetrieveAttributeResponse = CType(_serviceProxy.Execute(attributeRequest), RetrieveAttributeResponse)

     Console.WriteLine("Retrieved the attribute {0}.", attributeResponse.AttributeMetadata.SchemaName)
     '#End Region ' How to retrieve attribute

     '#Region "How to update attribute"
     ' Modify the retrieved attribute
     Dim retrievedAttributeMetadata As AttributeMetadata = attributeResponse.AttributeMetadata
     retrievedAttributeMetadata.DisplayName = New Label("Update String Attribute", _languageCode)

     ' Update an attribute retrieved via RetrieveAttributeRequest
     Dim updateRequest As UpdateAttributeRequest = New UpdateAttributeRequest With {
      .Attribute = retrievedAttributeMetadata,
      .EntityName = Contact.EntityLogicalName,
      .MergeLabels = False}

     ' Execute the request
     _serviceProxy.Execute(updateRequest)

     Console.WriteLine("Updated the attribute {0}.", retrievedAttributeMetadata.SchemaName)
     '                    #End Region ' How to update attribute

     '                    #Region "How to update state value"
     ' Modify the state value label from Active to Open.
     ' Create the request.
     Dim updateStateValue As UpdateStateValueRequest = New UpdateStateValueRequest With {
      .AttributeLogicalName = "statecode",
      .EntityLogicalName = Contact.EntityLogicalName,
      .Value = 1,
      .Label = New Label("Open", _languageCode)}

     ' Execute the request.
     _serviceProxy.Execute(updateStateValue)

     Console.WriteLine("Updated {0} state attribute of {1} entity from 'Active' to '{2}'.",
                       updateStateValue.AttributeLogicalName,
                       updateStateValue.EntityLogicalName,
                       updateStateValue.Label.LocalizedLabels(0).Label)
     '                    #End Region ' How to update state value

     '                    #Region "How to insert a new option item in a local option set"
     ' Create a request.
     Dim insertOptionValueRequest As InsertOptionValueRequest = New InsertOptionValueRequest With {
      .AttributeLogicalName = "new_picklist",
      .EntityLogicalName = Contact.EntityLogicalName,
      .Label = New Label("New Picklist Label", _languageCode)}

     ' Execute the request.
     Dim insertOptionValue As Integer = (CType(_serviceProxy.Execute(insertOptionValueRequest), InsertOptionValueResponse)).NewOptionValue

     Console.WriteLine("Created {0} with the value of {1}.", insertOptionValueRequest.Label.LocalizedLabels(0).Label, insertOptionValue)
     '#End Region ' How to insert a new option item in a local option set

     '#Region "How to change the order of options of a local option set"
     ' Use the RetrieveAttributeRequest message to retrieve  
     ' a attribute by it's logical name.
     Dim retrieveAttributeRequest As RetrieveAttributeRequest = New RetrieveAttributeRequest With {
      .EntityLogicalName = Contact.EntityLogicalName,
      .LogicalName = "new_picklist",
      .RetrieveAsIfPublished = True}

     ' Execute the request.
     Dim retrieveAttributeResponse As RetrieveAttributeResponse = CType(_serviceProxy.Execute(retrieveAttributeRequest), RetrieveAttributeResponse)

     ' Access the retrieved attribute.
     Dim retrievedPicklistAttributeMetadata As PicklistAttributeMetadata = CType(retrieveAttributeResponse.AttributeMetadata, PicklistAttributeMetadata)

     ' Get the current options list for the retrieved attribute.
     Dim optionList() As OptionMetadata = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray()

     ' Change the order of the original option's list.
     ' Use the OrderBy (OrderByDescending) linq function to sort options in  
     ' ascending (descending) order according to label text.
     ' For ascending order use this:
     Dim updateOptionList = optionList.OrderBy(Function(x) x.Label.LocalizedLabels(0).Label).ToList()

     ' For descending order use this:
     ' var updateOptionList =
     '      optionList.OrderByDescending(
     '      x => x.Label.LocalizedLabels[0].Label).ToList();

     ' Create the request.
     Dim orderOptionRequest As OrderOptionRequest = New OrderOptionRequest With {
      .AttributeLogicalName = "new_picklist",
      .EntityLogicalName = Contact.EntityLogicalName,
      .Values = updateOptionList.Select(Function(x) x.Value.Value).ToArray()}
     ' Set the properties for the request.
     ' Set the changed order using Select linq function 
     ' to get only values in an array from the changed option list.

     ' Execute the request
     _serviceProxy.Execute(orderOptionRequest)

     Console.WriteLine("Option Set option order changed")
     '#End Region ' How to change the order of options of a global option set

     ' NOTE: All customizations must be published before they can be used.
     _serviceProxy.Execute(New PublishAllXmlRequest())
     Console.WriteLine("Published all customizations.")

     DeleteRequiredRecords(promptForDelete)
    End Using

    ' Catch any service fault exceptions that Microsoft Dynamics CRM throws.
   Catch fe As FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault)
    ' You can handle an exception here or pass it back to the calling method.
    Throw
   End Try
  End Sub

  ''' <summary>
  ''' Deletes/Reverts the record that was created/changed for this sample.
  ''' <param name="prompt">Indicates whether to prompt the user to delete 
  ''' the records created in this sample.</param>
  ''' </summary>
  Public Sub DeleteRequiredRecords(ByVal prompt As Boolean)
   Dim deleteRecords As Boolean = True

   If prompt Then
    Console.WriteLine(vbLf &amp; "Do you want these entity records to be deleted? (y/n)")
    Dim answer As String = Console.ReadLine()

    deleteRecords = (answer.StartsWith("y") OrElse answer.StartsWith("Y"))
   End If

   If deleteRecords Then
    '                #Region "How to delete attribute"
    ' Delete all attributes created for this sample.
    For Each anAttribute As AttributeMetadata In addedAttributes
     ' Create the request object
     Dim deleteAttribute As DeleteAttributeRequest = New DeleteAttributeRequest With {
      .EntityLogicalName = Contact.EntityLogicalName,
      .LogicalName = anAttribute.SchemaName}
     ' Set the request properties 
     ' Execute the request
     _serviceProxy.Execute(deleteAttribute)
    Next anAttribute
    '#End Region ' How to delete attribute

    '#Region "How to remove inserted status value"
    ' Delete the newly inserted status value.
    ' Create the request object
    Dim deleteRequest As DeleteOptionValueRequest = New DeleteOptionValueRequest With {
     .AttributeLogicalName = "statuscode",
     .EntityLogicalName = Contact.EntityLogicalName,
     .Value = _insertedStatusValue}

    ' Execute the request
    _serviceProxy.Execute(deleteRequest)

    Console.WriteLine("Deleted all attributes created for this sample.")
    '#End Region ' How to remove inserted status value

    '#Region "Revert the changed state value"
    ' Revert the state value label from Open to Active.
    ' Create the request.
    Dim revertStateValue As UpdateStateValueRequest = New UpdateStateValueRequest With {
     .AttributeLogicalName = "statecode",
     .EntityLogicalName = Contact.EntityLogicalName,
     .Value = 1, .Label = New Label("Active", _languageCode)}

    ' Execute the request.
    _serviceProxy.Execute(revertStateValue)

    ' NOTE: All customizations must be published before they can be used.
    _serviceProxy.Execute(New PublishAllXmlRequest())

    Console.WriteLine("Reverted {0} state attribute of {1} entity from 'Open' to '{2}'.",
                      revertStateValue.AttributeLogicalName,
                      revertStateValue.EntityLogicalName,
                      revertStateValue.Label.LocalizedLabels(0).Label)
    '#End Region ' Revert the changed state value
   End If
  End Sub
#End Region ' How To Sample Code

#Region "Main"
  ''' <summary>
  ''' Standard Main() method used by most SDK samples.
  ''' </summary>
  ''' <param name="args"></param>
  Public Shared Sub Main(ByVal args() As String)
   Try
    ' Obtain the target organization's Web address and client logon 
    ' credentials from the user.
    Dim serverConnect As New ServerConnection()
    Dim config As ServerConnection.Configuration = serverConnect.GetServerConfiguration()

    Dim app As New WorkWithAttributes()
    app.Run(config, True)
   Catch ex As FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault)
    Console.WriteLine("The application terminated with an error.")
    Console.WriteLine("Timestamp: {0}", ex.Detail.Timestamp)
    Console.WriteLine("Code: {0}", ex.Detail.ErrorCode)
    Console.WriteLine("Message: {0}", ex.Detail.Message)
    Console.WriteLine("Plugin Trace: {0}", ex.Detail.TraceText)
                Console.WriteLine("Inner Fault: {0}", If(Nothing Is ex.Detail.InnerFault, "No Inner Fault", "Has Inner Fault"))
   Catch ex As TimeoutException
    Console.WriteLine("The application terminated with an error.")
    Console.WriteLine("Message: {0}", ex.Message)
    Console.WriteLine("Stack Trace: {0}", ex.StackTrace)
                Console.WriteLine("Inner Fault: {0}", If(Nothing Is ex.InnerException.Message, "No Inner Fault", ex.InnerException.Message))
   Catch ex As Exception
    Console.WriteLine("The application terminated with an error.")
    Console.WriteLine(ex.Message)

    ' Display the details of the inner exception.
    If ex.InnerException IsNot Nothing Then
     Console.WriteLine(ex.InnerException.Message)

     Dim fe As FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault) = TryCast(ex.InnerException, FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault))
     If fe IsNot Nothing Then
      Console.WriteLine("Timestamp: {0}", fe.Detail.Timestamp)
      Console.WriteLine("Code: {0}", fe.Detail.ErrorCode)
      Console.WriteLine("Message: {0}", fe.Detail.Message)
      Console.WriteLine("Plugin Trace: {0}", fe.Detail.TraceText)
                        Console.WriteLine("Inner Fault: {0}", If(Nothing Is fe.Detail.InnerFault, "No Inner Fault", "Has Inner Fault"))
     End If
    End If
    ' Additional exceptions to catch: SecurityTokenValidationException, ExpiredSecurityTokenException,
    ' SecurityAccessDeniedException, MessageSecurityException, and SecurityNegotiationException.

   Finally

    Console.WriteLine("Press <Enter> to exit.")
    Console.ReadLine()
   End Try

  End Sub
#End Region ' Main

 End Class
End Namespace

See Also

Extend the metadata model
Customize entity attribute metadata
Sample: Dump attribute metadata to a file
Work with attributes