WSDLによるSOAP連携

外部システムからWSDLによるSOAP連携によりデータを取得する機会があったのですが、以外とどこにも連携方法の情報がまとまっていなかった気がするのでまとめます。

WSDLからWebサービスプロキシクラスを作成する。
プロキシクラスを作成する方法は2つあって、1つはSrcUtil.exeをコマンドラインから実行する方法であり、もう1つはVisualStudioの「サービス参照の追加」のアドレスにエンドポイントのアドレスを指定する方法です。
※移動ボタンを押してもサービスが見つからない場合、アドレスの末尾に「?wsdl」を付けて再度移動ボタンを押してみてください。

f:id:katharsis1721:20170314000509p:plain

サービスが見つかりOKボタンを押すと、Webサービスプロキシクラス(CSファイル)とapp.configに設定が追加されます。

②①で作成したプロキシクラスを使用してWebサービスへ接続、データ取得する。

       //Webサービスプロキシクラスを使用して、Webサービスとの接続を行う。
       BasicHttpBinding myBinding = new BasicHttpBinding();
       myBinding.Name = "任意のBinding名";
       EndpointAddress endPointAddress = new EndpointAddress("公開されているエンドポイントのアドレス");
       ChannelFactory<IService> factory = new ChannelFactory<IService>(myBinding,endPointAddress);
       IService channel = factory.CreateChannel();

       //ここからは各WSDLの仕様に依存する。
       //各WSDLが用意しているメソッドを指定することでほしいデータを取得する。
       //ただ任意の引数を指定して、Responseデータを取得する方法に大きな違いはないはず。
       getHogeHogeResponse hogehogeResponse = new getHogeHogeResponse();
       hogehogeResponse = channel.getHogeHoge(任意の引数);

       factory.Close();


参考サイト

code.msdn.microsoft.com

www.smartllc.jp

Azure Recommendations APIを使ってDynamics CRM上から推奨製品をだしてみた

こちらに書かれているようにまだプレビュー版ですが(2016年9月現在)標準機能で「クロスセル製品推奨事項」機能が備わっています。

memo.tyoshida.me

この標準機能と似たようなことがMicrosoft Cognitive ServicesのAzure Recommendations APIを使ってできないかなと思い、以下のサイトを参考に試してみました。


blog.shibayan.jp

new_recommendationlink.htmlからnew_recommendation.htmlを読み出す形で作成し、
new_recommendationlink.htmlをWebリソースとしてCRM画面に埋め込んでいます。

new_recommendationlink.html

new_recommendation.html



関連性(Rating)の高い上位10件の製品を出力することができました。

XPathを使用してExcelのXMLスプレッドシートからセルの値を取得する

ExcelXMLスプレッドシートからセルの値を取得してなんやかんやとデータ操作したい場合があります。
例えばXMLスプレッドシートを使用してデータインポートやエクスポート時にデータを更新するなど。

ExcelXMLスプレッドシート名前空間は「urn:schemas-microsoft-com:office:spreadsheet」であるため、AddNamespaceで名前空間とそのプレフィックスを指定する必要があります。

参考サイト
XPath and Excel spreadsheet
http://forums.asp.net/t/377921.aspx?XPath+and+Excel+spreadsheet

名前空間を指定してXPathを実行する。
http://devlights.hatenablog.com/entry/20070906/p1

Dynamics CRMで作成可能なフィールド項目一覧

Dynamics CRM 2016時点で作成可能なフィールド一覧をまとめてみました。

# データの種類 形式 データ型 最小値 最大値
1 1行テキスト 電子メール nvarchar 1 4000
2 1行テキスト テキスト nvarchar 1 4000
3 1行テキスト テキスト領域 nvarchar 1 4000
4 1行テキスト URL nvarchar 1 4000
5 1行テキスト 株式銘柄コード nvarchar 1 4000
6 1行テキスト ふりがな nvarchar 1 4000
7 1行テキスト 電話 nvarchar 1 4000
8 オプションセット - int -2147483648 2147483648
9 2つのオプション ラジオボタン bit 0(FALSE) 1(TRUE)
10 2つのオプション チェックボックス bit 0(FALSE) 1(TRUE)
11 2つのオプション 選択リスト bit 0(FALSE) 1(TRUE)
12 整数 なし int -2147483648 2147483647
13 整数 期間 int -2147483648 2147483647
14 整数 タイムゾーン int -2147483648 2147483647
15 整数 言語 int -2147483648 2147483647
16 浮動小数点数 小数点桁数0〜5桁の範囲で指定可能 float -100000000000 100000000000
17 10進数 小数点桁数0〜10桁の範囲で指定可能 decimal -100000000000 100000000000
18 通貨型 小数点桁数0〜4桁の範囲で指定可能 money -922337203685477 922337203685477
19 複数行テキスト - ntext 1 1048576
20 日付と時間 日付のみ datetime 1900/1/1 9999/12/30
21 日付と時間 日付と時間 datetime 1900/1/1 0:00 9999/12/30 23:59
22 イメージ - image - -
23 検索 - identifier - -

イメージフィールドはこの他に以下のような特徴があるようですね。
・各エンティティに1つのみ設定可能
・検索可能項目には「いいえ」のみ指定可能(検索不可)
・任意項目のみ指定可能(必須不可)
・実際のイメージデータは内部エンティティImageDescriptorで管理される

参考サイト
www.pine4.net

technet.microsoft.com

locationオブジェクトを使ったサーバーURLの取得方法

フォーム内でサーバーURLを取得する場合、Xrm.Page.context.getClientUrl()が使用されますが、
リバースプロキシ経由と直接サーバー接続する2パターンで接続する場合など、
ドメイン名がそれぞれ異なるためXrm.Page.context.getClientUrl()が使用できないケースがあります。

その場合は、以下のようにwindow.locationオブジェクトを使ってURLを取得すれば良いです。

    var cURL = document.location.href;
    var domain = document.location.host;
    var jsHost = (document.location.protocol) + '//';
    var org = cURL.split('/')[3];
    var crmUrl = jsHost + domain + '/' + org;
    
    var ODataPath = crmUrl + "/XRMServices/2011/OrganizationData.svc/";
    
    //リバースプロキシ経由で接続する場合などは、例えば以下のようにgetClientUrl()は使えない
    //var ODataPath = Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/";

Dynamics CRMエンティティ一覧がほしい時に実行するSQL

Dynamics CRMのエンティティ一覧がほしい時に実行するSQLです。
ソリューションファイルをダウンロード、加工したりする手間を省きたいときなどに使用します。

SELECT
	 MAX(CASE ObjectColumnName WHEN 'LocalizedName' THEN tmp.Label ELSE NULL END) AS LocalizedName
	,MAX(CASE ObjectColumnName WHEN 'Description' THEN tmp.Label ELSE NULL END)   AS Description
FROM 
(
SELECT 
	 ObjectId
	,ObjectColumnName
	,Label
FROM   MetadataSchema.LocalizedLabel  
INNER JOIN  EntityView 
ON     LocalizedLabel.ObjectId = EntityView.EntityId
WHERE  ObjectColumnName IN ('LocalizedName','Description')
) tmp
GROUP BY tmp.ObjectId

参考サイト
dev.classmethod.jp

入力パラメータが指定されていればWhere句の条件に追加する方法

PowerShellからSQLを使ってデータ取得し、取得した結果をCSV出力する処理を行います。
その際、Where句の条件を入力パラメータとして指定して、入力パラメータがあればそのパラメータを条件として追加。
無い場合はWhere句の条件を付けずにSQLを実行する方法です。

Param(
    [Parameter(Mandatory = $true,Position = 0)]
    [DateTime]
    $a,
    [Parameter(Mandatory = $true,Position = 1)]
    [AllowEmptyString()]
    [String]
    $b
)

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Data")

$connectionString = "Data Source=.;Initial Catalog=[DB名];Integrated Security=True;"
$Con = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$Con.Open()

$Cmd = New-Object System.Data.SqlClient.SqlCommand
$Cmd.Connection = $Con

$DateFrom = $a.ToString('yyyy-MM-dd HH:mm:ss')

$SQL = "SELECT * FROM [dbo].[hogehoge] WHERE Column1 >= '$DateFrom'"

$Where_SQL = $null
#$bパラメータが指定されていた場合、SQLに条件を追加
if($b){
    $Where_SQL = "AND Column2 = '$b'"
}

$Cmd.CommandText = $SQL + $Where_SQL

$Datas = New-Object System.Collections.ArrayList
$ClientReader = $Cmd.ExecuteReader()
while ($ClientReader.Read()) {
    $Data = New-Object PSObject | Select-Object AttributeMask
    $Data.AttributeMask = $ClientReader["AttributeMask"].ToString()
    [void]$Datas.Add($Data)
} 

$OutputFilename = "C:\Temp\test.csv"
$Datas | Export-Csv $OutputFilename -Encoding Default

$ClientReader.Dispose()

$Con.Close()
$Con.Dispose()

$bは入力必須項目ですが、パラメータ検証属性「AllowEmptyString」付いているため空文字列を指定することが可能です。

$Where_SQL = $null
#$bパラメータが指定されていた場合、SQLに条件を追加
if($b){
    $Where_SQL = "AND Column2 = '$b'"
}

上記の条件分岐で$bパラメータが指定されていた場合は、$Where_SQLに条件を文字列として追加し、
$bパラメータが指定されていない場合は、$Where_SQLをNULLとします。

$Cmd.CommandText = $SQL + $Where_SQL

後は、変数を連結させれば終わり。