エンティティの論理名や表示名、エンティティのプロパティの型情報はMetadataServiceを経由して取得します。今回は、設置型のAD認証と、IFD構成の2種類のケースでMetadataServiceに接続する方法と、エンティティのメタデータを取得するサンプルを掲載します。

確認環境

  • 動作環境:Windows Server 2003 , Dynamics CRM 4.0 IFD構成
  • 作成環境:Visual Studio 2008 Professional
  • .NET 3.5

1.ソリューションの作成

Visual Studio を起動し、空のソリューションを作成します。本サンプルはコンソールアプリケーションとして開発します。ソリューションエクスプローラを右クリックし、コンソールプロジェクトを追加します。動作には、Dynamics CRM SDK に付属する、microsoft.crm.sdk.dll、microsoft.crm.sdktypeproxy.dllおよび、System.Web.Service.dll の参照が必要ですので、プロジェクトの参照で追加してします。

1.1 CrmDiscoveryService 用プロキシクラスの作成

CrmDiscoveryServiceを使用するため、Dynamics CRM SDK に付属するwsdlフォルダのcrmdiscoveryservice.wsdlからプロキシクラスを作成します。

プロキシクラスは次のSDKのwsdlフォルダに移動して次のコマンドで作成しました。

wsdl /namespace:Microsoft.Crm.Sdk.Discovery  crmdiscoveryservice.wsdl

作成したプロキシクラスCrmDiscoveryService.csをプロジェクトに含めます。

2.MetadataServiceの作成

設置型のAD認証を使用し実行ユーザの資格情報を使用する場合は、CRMサーバのUrl + "/MSCRMServices/2007/MetadataService.asmx"に接続することでMetadataServiceを使用します。GetMetadataServiceには、CRMサーバのUrlと組織名を引数に指定してMetadataServiceを作成します。

/// <summary>
/// 設置型AD認証用
/// </summary>
/// <param name="discoveryServerUrl">CRMサーバのUrl</param>
/// <param name="organizationName">組織名</param>
/// <returns></returns>
public static MetadataService GetMetadataService(string crmServerUrl, string organizationName)
{
    CrmAuthenticationToken token = new CrmAuthenticationToken();
    token.OrganizationName = organizationName;
    MetadataService service = new MetadataService();
    UriBuilder uriBuilder = new UriBuilder(crmServerUrl);
    uriBuilder.Path = "/MSCRMServices/2007/MetadataService.asmx";
    service.Url = uriBuilder.Uri.ToString();
    service.UseDefaultCredentials = true;
    service.CrmAuthenticationTokenValue = token;

    return service;
}

IFD構成の場合は、一度DiscoveryServiceに接続して認証トークンを作成し、DiscoveryService を介して発見した OrganizationDetail の  CrmMetadataServiceUrlプロパティの値を接続先のUrlとして接続します。未検証ですが、CrmImpersonatorを使用する場合は、DiscoverServiceを使用して取得するCrmMEtadataServiceUrlのプロパティからMetadataServiceのUrlを取得することはできないようです。

/// <summary>
/// IFD構成用
/// </summary>
/// <param name="discoveryServerUrl">ディスカバリーサービスのURL</param>
/// <param name="organizationName">組織名</param>
/// <param name="domain">ドメイン名</param>
/// <param name="username">アカウント</param>
/// <param name="password">パスワード</param>
/// <returns></returns>
public static MetadataService GetMetadataServiceByIFD(string discoveryServerUrl, string organizationName, string domain, string username, string password)
{
    string userid = domain + @"\" + username;

    UriBuilder uriBuilder = new UriBuilder(discoveryServerUrl);
    uriBuilder.Path = "/MSCRMServices/2007/SPLA/CrmDiscoveryService.asmx";
    CrmDiscoveryService disco = new CrmDiscoveryService();
    disco.Url = uriBuilder.Uri.ToString();
    disco.UseDefaultCredentials = false;
    disco.Credentials = new NetworkCredential(username, password, domain);

    RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
    orgRequest.UserId = userid;
    orgRequest.Password = password;
    RetrieveOrganizationsResponse orgResponse =
        (RetrieveOrganizationsResponse)disco.Execute(orgRequest);

    bool found = false;
    string serviceUrl = string.Empty;
    string metadataServiceUrl = string.Empty;
    foreach (OrganizationDetail orgdetail in orgResponse.OrganizationDetails)
    {
        if (orgdetail.OrganizationName == organizationName)
        {
            found = true;
            serviceUrl = orgdetail.CrmServiceUrl;
            metadataServiceUrl = orgdetail.CrmMetadataServiceUrl;
            break;
        }
    }
    if (found == false) return null;

    RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
    ticketRequest.OrganizationName = organizationName;
    ticketRequest.UserId = userid;
    ticketRequest.Password = password;
    RetrieveCrmTicketResponse ticketResponse =
        (RetrieveCrmTicketResponse)disco.Execute(ticketRequest);

    CrmAuthenticationToken token = new CrmAuthenticationToken();
    token.AuthenticationType = 2; // IFD, ADの場合0
    token.OrganizationName = organizationName;
    token.CrmTicket = ticketResponse.CrmTicket;

    MetadataService service = new MetadataService();
    service.Url = metadataServiceUrl;
    service.CrmAuthenticationTokenValue = token;
    service.UseDefaultCredentials = true;

    return service;
}

 3. Entityのメタデータの検索

特定のEntityのメタデータとCRM上のすべてのEntityのメタデータを取得するサンプルを掲載します。

3.1 エンティティのメタデータの作成

エンティティsystemuserのエンティティのメタデータとプロパティ情報を検索するサンプルを掲載します。

static void Main(string[] args)
{
    MetadataService service = GetMetadataServiceByIFD("http://crmorg01.vs2k3.crm1.local/", "crmorg01", "crm1", "crmadmin", "password");
    RetrieveSingleEntityMetadata(service);
    Console.ReadLine();
}
public static void RetrieveSingleEntityMetadata(MetadataService service)
{
    RetrieveEntityRequest request = new RetrieveEntityRequest();
    request.EntityItems = Microsoft.Crm.Sdk.Metadata.EntityItems.All;
    request.RetrieveAsIfPublished = true;
    request.LogicalName = Microsoft.Crm.SdkTypeProxy.EntityName.systemuser.ToString();

    RetrieveEntityResponse response = (RetrieveEntityResponse)service.Execute(request);

    // 属性情報を出力する
    foreach (AttributeMetadata att in response.EntityMetadata.Attributes)
    {
        string attType = att.AttributeType.Value.ToString();
        string attDispName = (att.DisplayName.UserLocLabel == null) ? "(null)" : att.DisplayName.UserLocLabel.Label;
        string attLogicName = att.LogicalName;
        string template = "タイプ:{0}, 表示名:{1}, 論理名:{2}";
        Console.WriteLine(string.Format(template, attType, attDispName, attLogicName));
    }
}

サンプルではsystemuserのメタデータをEntityItem.All(エンティティ、属性、関連情報すべて)を取得します。実行結果は次のようにします。

 

 

3.2 Dynamics CRMの全てのエンティティのメタデータを検索する

エンティティのメタデータを取得するのは重い処理のため、検索オプションにEntitiesOnlyを指定してすべてのEntityのメタデータを検索します。

static void Main(string[] args)
{
    MetadataService service = GetMetadataService("http://localhost/", "crmorg01");
    RetrieveAllEntityMetadata(service);
    Console.ReadLine();
}
public static void RetrieveAllEntityMetadata(MetadataService service)
{
    RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest();
    request.MetadataItems = MetadataItems.EntitiesOnly;
    request.RetrieveAsIfPublished = false;

    RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)service.Execute(request);

    foreach (EntityMetadata meta in response.CrmMetadata)
    {
        string template = "エンティティ名:{0}, 論理名:{1}";
        Console.WriteLine(string.Format(template, meta.DisplayName, meta.LogicalName));
    }
}

AD認証を使用し、処理ユーザの資格情報を使用してMetadataServiceに接続し、すべてのエンティティのメタデータを取得しています。メタデータの取得は重い処理なので、EntityItemsの指定でMetadataItems.EntityiesOnly と指定しています。

実行結果は次のようになります。

 

 

4.まとめ

今回の説明は以上です。CRM 4.0 からはメタデータの検索だけでなく、更新などができるようになっているため、カスタムアプリケーションを作成する場合、知っておくと便利だと思います。

間違い、指摘等がありましたらご連絡ください。