エンティティの論理名や表示名、エンティティのプロパティの型情報は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 からはメタデータの検索だけでなく、更新などができるようになっているため、カスタムアプリケーションを作成する場合、知っておくと便利だと思います。
間違い、指摘等がありましたらご連絡ください。
ところで、メタデータの更新(CRMにデータをVBにより変更する)に苦戦しており
何かいい情報かサンプルがあればぜひご教授いただけないでしょうか?
CRMの在庫エンティティーを外部プログラムで更新したいのです。
SQLサーバーのデータを直接さわるのでは本来の解決にならないと思っております。
http://handcraft.blogsite.org/ComponentGeek/ShowArticle/129.aspxにサンプルを作成してみました。VBではないのであしからず。