【Dynamics CRM 2011】CrmConnectionを使ってDynamicsへの認証・接続を行う
MSDNを読んでいると「Dynamicsへの認証はSDKに含まれているサンプルコードのcrmservicehelpers.cs(sdk->samplecode->cs->helpercode内)を使うと便利だよ!」みたいな記述をちらほら見かけるのですが、どうにもコンソールアプリケーション以外に適用し辛く、コードを参考にするにはあまりにも複雑な仕組みになっています。
そこでCrmConnectionと言うクラスを使ってもっと簡単にDynamicsへの接続を行いたいと思います。
CrmConnectionへ渡すConnectionString
CrmConnectionはParseメソッドにConectionStringを直接渡すか、コンストラクタでConnectionStringSettingsを渡すことで取得できます。
OrganizationServiceやCrmOrganizationServiceContextのコンストラクタにこのCrmConnectionを受け取るオーバーロードが存在するので、実質ConnectionStringだけで接続と認証を済ませることが出来るわけです。
実際にどんなConnectionStringを渡すかですが、このドキュメントに全部書いてあります。
CrmConnectionを使ったいつものクソみたいなサンプルコードもあるので、これらのドキュメントを参考にしつつ、実際にやってみましょう。
コード
ActiveDirectoryの場合はURLに加えてドメイン名、ユーザ名、パスワードを渡してあげればいいみたいです。
using System; using System.Linq.Expressions; using System.Text; using Microsoft.Xrm.Client; using Microsoft.Xrm.Client.Services; namespace CrmConnectionTest { public class CrmConnecter { public static OrganizationService Connect(string url, string domain, string userName, string password) { var connectionString = CreateConnectionString ( Url => url, Domain => domain, Username => userName, Password => password ); var con = CrmConnection.Parse(connectionString); return new OrganizationService(con); } private static string CreateConnectionString(params Expression<Func<object, object>>[] exprs) { var sb = new StringBuilder(); foreach (var expr in exprs) { var obj = expr.Compile().Invoke(null); if (obj == null) continue; var name = expr.Parameters[0].Name; var val = obj.ToString(); sb.Append(name).Append('=').Append(val).Append(';'); } return sb.ToString(); } } }
これだけでOKです。
他の認証方法を使ったConnectionStringの作り方はさっきのドキュメントの下の方に書いてあります。
まとめ
汎用的なものを作る場合はともかく、ちょっと実験したいな、ってぐらいなら、これで十分です。
[2014/04/03追記]
OrganizationServiceProxyを作成する場合
OrganizationServiceではなくOrganizationServiceProxyが欲しいケースもあると思います。
その場合もCrmConnectionを使うと簡単です。
public static OrganizationServiceProxy Connect(string server, string organization, string domain, string userName, string password) { var url = "http://" + server + "/" + organization + "/XRMServices/2011/Organization.svc"; var connectionString = CreateConnectionString ( Url => url, Domain => domain, Username => userName, Password => password ); var con = CrmConnection.Parse(connectionString); return new OrganizationServiceProxy(con.ServiceUri, con.HomeRealmUri, con.ClientCredentials, con.DeviceCredentials); }
OrganizationServiceProxyを作成する場合(マルチスレッド編)
さらにマルチスレッドでやりたいとなると、もう一工夫必要です。
と言っても
IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(organizationUrl)); AuthenticationCredentials authCredentials = orgServiceManagement.Authenticate(credentials);
の部分を
var con = CrmConnection.Parse(connectionString); var orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(con.ServiceUri); var authCredentials = orgServiceManagement.Authenticate(new AuthenticationCredentials{ HomeRealm = con.HomeRealmUri, ClientCredentials = con.ClientCredentials, });
に書き換えるだけです。
メタデータを保持する必要があるため、流石にstaticなメソッドだけでは厳しいのでこんな感じにしました。
using System; using System.Linq.Expressions; using System.Text; using Microsoft.Xrm.Client; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; namespace CrmConnectionTest { public class CrmConnecter { private readonly IServiceManagement<IOrganizationService> _manager; private readonly AuthenticationCredentials _credential; public CrmConnecter(string server, string organization, string domain, string userName, string password) { var url = "http://" + server + "/" + organization + "/XRMServices/2011/Organization.svc"; var connectionString = CreateConnectionString ( Url => url, Domain => domain, Username => userName, Password => password ); var connection = CrmConnection.Parse(connectionString); _manager = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(connection.ServiceUri); _credential = _manager.Authenticate(new AuthenticationCredentials { HomeRealm = connection.HomeRealmUri, ClientCredentials = connection.ClientCredentials, }); } public OrganizationServiceProxy GetProxy() { var proxy = new OrganizationServiceProxy(_manager, _credential.ClientCredentials); proxy.EnableProxyTypes(); return proxy; } private static string CreateConnectionString(params Expression<Func<object, object>>[] exprs) { var sb = new StringBuilder(); foreach (var expr in exprs) { var obj = expr.Compile().Invoke(null); if (obj == null) continue; var name = expr.Parameters[0].Name; var val = obj.ToString(); sb.Append(name).Append('=').Append(val).Append(';'); } return sb.ToString(); } } }
こんな感じに使います。
var connecter = new CrmConnecter(server, organization, domain, userName, password); Parallel.For<OrganizationServiceProxy>(0, count , () => connecter.GetProxy() , (i, state, proxy) => { // TODO: OrganizationServiceProxyをつかったいろいろ // ex.) proxy.Update(entity); } , proxy => proxy.Dispose());
[2014/04/03追記ここまで]
参考
- Dynamics CRM 2011 SDK 認証の選択肢 - Japan Dynamics CRM Team Blog - Site Home - MSDN Blogs
- サンプル シンプルな接続クイックを Microsoft Dynamics CRM 2011 と Microsoft Dynamics CRM Online の使用開始
- Microsoft Dynamics CRM への簡略化された接続
- Connection/Object pool for OrganizationServiceProxy in XRM/Dynamics CRM 2011 - Stack Overflow
- Dynamics CRM 2011 SDK 5.0.12 マルチスレッド環境でのサービスプロキシ生成 - Japan Dynamics CRM Team Blog - Site Home - MSDN Blogs