Retrieving Metadata

The MetadataService uses an object structure that differs from the CrmService. All metadata objects inherit from the CrmMetadata object. A number of objects are also shared by the MetadataService and the CrmService Web Service (for example, CRM data types).

Warning

Warning

Watch out for type name collisions when using both the MetadataService and the regular Web service inside a class. You might need to partition your code better or use namespace aliasing to prevent compilation issues.

Names Used in the MetadataService

It’s important to understand the difference between the logical names and schema names used by the MetadataService. In most cases these names are identical (with some variation for case differences). Be alert when comparing values; you may need to adjust your casing appropriately.

  • Logical name. The unique property name or class name of an object. The logical name is always lowercase. In the user interface, the logical name is simply referred to as Name.

  • Schema name. The unique name used by CRM to store the object in the database. The schema name often uses Pascal casing.

New schema names and logical names must conform to a naming convention and have a customization prefix (between two and eight characters with an underscore). Examples include: new_ and contoso_.

Retrieving Entities

CRM’s metadata essentially consists of a collection of entities. All other pieces of metadata (attributes, relationships, and so on) are linked by an entity. The EntityMetadata object describes the schema information for a CRM entity. Most of the EntityMetadata’s properties are normal CRM types (for example, CrmBoolean) that describe the characteristics of the entity. Each entity has five important collections of related objects, which we will discuss in detail later in the chapter:

  • Privileges

  • Attributes

  • ManyToManyRelationships

  • ManyToOneRelationships

  • OneToManyRelationships

RetrieveEntityRequest

You use RetrieveEntityRequest—with its corresponding response message RetrieveEntityResponse—to retrieve a single EntityMetadata object from CRM. The RetrieveEntityRequest object has three properties that should always be set:

  • EntityItems

  • RetrieveAsIfPublished

  • LogicalName

The EntityItems property determines whether the five important collections (Privileges, Attributes, ManyToManyRelationships, ManyToOneRelationships, and OneToManyRelationships) are populated when the entity data is retrieved. Retrieving these collections is a heavyweight task, and for performance reasons a developer might choose to retrieve only some of the entity’s related data. Because EntityItems is marked with FlagsAttribute, multiple values can be combined using a bitwise OR (the | operator in C#). The EntityItems enum has the following values:

  • EntityItems.All. Retrieves privileges, attributes, ManyToManyRelationships, ManyToOneRelationships, and OneToManyRelationships.

  • EntityItems.EntityOnly. Used when you only want the basic entity metadata returned and none of the related collections populated. All the other EntityItems values will include the entity metadata as well, so while it will not cause an error, this value never needs to be combined with the other EntityItems values.

  • EntityItems.IncludeAttributes. Specifies that the Attribute collection should be populated.

  • EntityItems.IncludePrivileges. Specifies that the Privileges collection should be populated.

  • EntityItems.IncludeRelationships. Specifies that the ManyToManyRelationships, ManyToOneRelationships, and OneToManyRelationships collections should be populated.

The RetrieveAsIfPublished property determines whether unpublished metadata is shown. When this property is set to true, CRM simulates an entity publish operation when retrieving the metadata. If you want to retrieve metadata as experienced by end users, set this property to false. If you want to retrieve metadata as experienced by customizers (in the customization user interface of the application), set this property to true.

The LogicalName property determines which entity is retrieved.

More Info

More Info

Refer to the following article in the Microsoft Dynamics CRM 4.0 Software Development Kit (SDK), which provides additional information regarding logical names: http://msdn.microsoft.com/en-us/library/cc151044.aspx.

The following code shows how to retrieve a single entity from CRM:

MetadataService metadataService = GetMetadataService("contoso");

RetrieveEntityRequest request = new RetrieveEntityRequest();
request.EntityItems = EntityItems.All;
request.RetrieveAsIfPublished = true;
request.LogicalName = "account";
RetrieveEntityResponse response = (RetrieveEntityResponse)metadataService.Execute(request);

RetrieveAllEntitiesRequest

RetrieveAllEntitiesRequest retrieves all entities in CRM (System, Custom, and Customizable). You also need to set the RetriveAsIfPublished property and determine the depth and detail of the related entity collections using the MetadataItems property. RetrieveAllEntitiesRequest uses the MetadataItems property to govern the level of detail returned by the request. The MetadataItems property is an enum type that is also named MetadataItems. Similar to the EntityItems enum, multiple values can be combined to control the retrieval behavior as follows:

  • MetadataItems.All Retrieve. Privileges, Attributes, ManyToManyRelationships, ManyToOneRelationships, and OneToManyRelationships. Because this value already returns everything, it should not be combined with other values.

  • MetadataItems.EntitiesOnly. Return only the entity metadata and not the related collections. All the other MetadataItems values include the entity metadata as well, so you never need to combine EntitiesOnly with the other values.

  • MetadataItems.IncludeAttributes. Specifies to populate the Attribute collection.

  • MetadataItems.IncludePrivileges. Specifies to populate the Privileges collection.

  • MetadataItems.IncludeRelationships. Specifies to populate the ManyToMany-Relationships, ManyToOneRelationships, and OneToManyRelationships collections.

Notice that RetrieveAllEntitiesResponse contains an array of CrmMetadata objects. This array will only ever contain EntityMetadata objects (which inherit from CrmMetadata).

The following code retrieves all entities from CRM and writes their logical names to the console. Figure 8-3 displays the resulting output.

MetadataService metadataService = GetMetadataService("contoso");

RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest();
request.MetadataItems = MetadataItems.EntitiesOnly;
request.RetrieveAsIfPublished = false;
RetrieveAllEntitiesResponse response =
  (RetrieveAllEntitiesResponse)metadataService.Execute(request);

foreach (EntityMetadata entity in response.CrmMetadata)
{
    Console.WriteLine(entity.LogicalName);
}
RetrieveAllEntities sample code output

Figure 8-3. RetrieveAllEntities sample code output

Retrieving Attributes and Relationships

You can retrieve attributes and relationships in one of two ways: individually, by using the appropriate Retrieve message specifying their unique logical names, or as part of a collection in the RetrieveEntityRequest or RetrieveAllEntities request. The MetadataService does not offer a message to retrieve all of an organization’s attributes or relationships. Both requests also make use of the RetrieveAsIfPublished property, which you should always set. (See the section "Retrieving Entities" earlier in the chapter for more information on this topic.)

Attribute Considerations

When retrieving an attribute with RetriveAttributeRequest you simply provide the logical names of the attribute and its parent entity. You can also use the attribute’s unique MetadataId (a GUID) if known.

Tip

Tip

You can often substitute the MetadataId for logical names of entities, attributes, and relationships. Note that these IDs are not consistent between organizations.

Relationship Considerations

When retrieving a relationship with RetrieveRelationshipRequest, you simply provide the logical name of the relationship or its MetadataId (a GUID). You do not need to specify any parent entity information. RetrieveRelationshipRequest returns a RelationshipMetadata object. However, you need to cast this object to one of its child types: OneToManyMetadata or ManyToManyMetadata. ManyToOneMetadata does not exist—a many-to-one relationship is simply a one-to-many relationship viewed from a different perspective.

Two properties often cause confusion with the OneToManyMetadata object: ReferencedEntity and ReferencingEntity. Table 8-1 lists how the user interface describes each property.

Table 8-1. Reference Entity Labels

Object Property

Label in the Customization User Interface

ReferencedEntity

Primary Entity

ReferencingEntity

Related Entity

RetrieveAllEntitiesResponse contains a copy of each one-to-many relationship in the appropriate arrays (OneToManyRelationships and ManyToOneRelationships) for both the Referenced and Referencing entities, as shown in Table 8-2.

Table 8-2. Reference Entity Array Relationship

Entity

Array Relationship Is Found In

ReferencedEntity

OneToManyRelationships

ReferencingEntity

ManyToOneRelationships

You can locate a relationship’s logical name in the customization user interface. Figure 8-4 shows the relationship’s logical name in the Name field of the relationship customization form.

One-to-many relationship customization form

Figure 8-4. One-to-many relationship customization form

The following code sample demonstrates how to retrieve the equipment_accounts relationship shown in Figure 8-4 and display the Referencing and Referenced entity information.

MetadataService metadataService = GetMetadataService("contoso");

RetrieveRelationshipRequest request = new RetrieveRelationshipRequest();
request.Name = "equipment_accounts";
request.RetrieveAsIfPublished = true;
RetrieveRelationshipResponse response =
    (RetrieveRelationshipResponse)metadataService.Execute(request);

if (response.RelationshipMetadata is OneToManyMetadata)
{
    OneToManyMetadata equipmentAccounts =
     (OneToManyMetadata)response.RelationshipMetadata;

    Console.Write("Referenced Entity: ");
    Console.WriteLine(equipmentAccounts.ReferencedEntity);

    Console.Write("Referencing Entity: ");
    Console.WriteLine(equipmentAccounts.ReferencingEntity);
}

This relationship creates a lookup attribute on the account to the equipment entity.

Therefore, the Account entity is referencing the Equipment entity, and the Equipment entity is being referenced by the Account entity. Figure 8-5 shows console output for the sample.

Console output for relationship retrieval sample

Figure 8-5. Console output for relationship retrieval sample

Multilingual Strings

Many of the properties of the objects in the MetadataService make use of multilingual strings. The CrmLabel object facilitates the storage of such items. In Microsoft Dynamics CRM 3.0, properties such as the Display Name of an entity (Account, Contact, Lead, Project, and so on) were stored as a simple string in the metadata. With the introduction of multilingual user interface features in Microsoft Dynamics CRM 4.0, this is no longer practical given the normalization of this information.

Tip

Tip

We recommend that you install and activate at least one additional language on all your development servers, even if you don’t need multiple languages right now. Installing multiple languages will expose new defects or scenarios that you would not experience with only one language installed. Microsoft provides the various language packs at no cost. You can download them from http://www.microsoft.com/downloads.

The CrmLabel object stores the strings for a particular property inside an array of LocLabel objects. A LocLabel object consists of a string property (for the actual string user by the user interface) and an int property (the LCID). LCIDs (Locale IDs) indicates the Language and Culture/Region of the string.

More Info

More Info

A full list of LCIDs is available from Microsoft’s Web site: http://www.microsoft.com/globaldev/reference/lcid-all.mspx.

The following code is a useful helper method that creates an instance of CrmLabel and initializes it with a LocLabel value for a single locale. We will take advantage of this helper method in later code samples in this chapter.

public static CrmLabel CreateLabel(string label, int languageCode)
{
    CrmLabel crmLabel = new CrmLabel();
    crmLabel.LocLabels = new LocLabel[1];
    crmLabel.LocLabels[0].Label = label;
    crmLabel.LocLabels[0].LanguageCode = new CrmNumber();
    crmLabel.LocLabels[0].LanguageCode.Value = languageCode;
    return crmLabel;
}

We recommend that metadata developers always assume that CRM may have multiple languages installed. Table 8-3 lists the language packs that Microsoft Dynamics CRM offered at the time this book went to press.

Table 8-3. Microsoft Dynamics CRM 4.0 language packs

Arabic

French

Norwegian

Chinese (Hong Kong)

German

Polish

Chinese (Simplified)

Greek

Portuguese (Brazil)

Chinese (Traditional)

Hebrew

Portuguese (Iberian)

Czech

Hungarian

Russian

Danish

Italian

Spanish

Dutch

Japanese

Swedish

English

Korean

Turkish

Finnish

  

More Info

More Info

Please refer to the Microsoft Dynamics CRM 4.0 Implementation Guide for details on downloading, installing, and activating language packs.

CRM also provides a handy helper property, UserLocLabel, which is a property of the CrmLabel object. This string property is set to the string of the LocLabel for the LCID of the user making the call. For example, if my language is set to French (LCID 1036), the string value of the UserLocLabel will be the 1036 string.

Tip

Tip

Never try to set the UserLocLabel property. It is read-only!

In the following example the code displays the strings for the DisplayCollectionName property (the entity plural name) in the console. This code assumes you have already retrieved the EntityMetadata object (called entity here) from the MetadataService. Figure 8-6 shows the console output.

//Assumes that an EntityMetadata object called entity was created and retrieved from CRM

Console.WriteLine("Entity Plural Name Strings");
Console.WriteLine();

Console.WriteLine("User LocLabel");
Console.WriteLine(entity.DisplayCollectionName.UserLocLabel.LanguageCode.Value);
Console.WriteLine(entity.DisplayCollectionName.UserLocLabel.Label);
Console.WriteLine();

Console.WriteLine("LocLabel Collection");
foreach (LocLabel loclabel in entity.DisplayCollectionName.LocLabels)
{
    Console.WriteLine(loclabel.LanguageCode.Value);
    Console.WriteLine(loclabel.Label);
    Console.WriteLine();
}
Language strings console application

Figure 8-6. Language strings console application

As Figure 8-6 shows, the organization had U.S. English (1033) and French (1036) installed and activated.

Available Languages

You should only use LCIDs for languages installed on the Microsoft Dynamics CRM server. Attempts to use LCIDs for unavailable languages will silently fail. Use RetrieveAvailableLanguagesRequest with the CrmService to retrieve an array of LCIDs in the LocalIds property of the RetrieveAvailableLanguagesResponse object.

The following code shows how to retrieve the available languages and display them in the console:

//Connect to the regular CRM Service
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 0;
token.OrganizationName = "contoso";

CrmService crmService = new CrmService();
crmService.CrmAuthenticationTokenValue = token;
crmService.Credentials = CredentialCache.DefaultCredentials;
crmService.Url = "http://crm/mscrmservices/2007/crmservice.asmx";

RetrieveAvailableLanguagesRequest request = new RetrieveAvailableLanguagesRequest();
RetrieveAvailableLanguagesResponse response =
    (RetrieveAvailableLanguagesResponse) crmService.Execute(request)

Console.WriteLine("Available Languages");
foreach (int i in response.LocaleIds)
{
    Console.WriteLine(i);
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset