ODCでは、Consume/Expose SOAP Web Serviceの作成ができない(OutSystems 11ではできた)。
Exposeの方は無理だが、ConsumeならExternal Logicを使った代替案がある。
Supporting SOAP in ODCに手順が載っているので、ほぼそのままになるが以下で実地に確認してみる。
手順サマリ
- SOAPのAPIからWSDLファイルを取得する
- dotnet-svcutilでWSDLファイルからSOAPサービスのクライアントコードを生成
- External Logicプロジェクトを用意
- 用意したクライアントコードをプロジェクト下に移動し、利用コードを書く
- External Logicをアップロードして利用する
環境情報
ODC
ODC Studio(Version 1.4.13)
Visual Studio Code (Version 1.88.1)
OutSystems 11 (SOAPサービス作成用)
Personal Environment(Version 11.27.0 (Build 42818))
Service Studio(Version 11.54.64)
SOAPのサービスを用意する
OutSystems 11のExpose SOAP Web Serviceを使う
Service StudioでOutSystems 11環境に接続し、「Expose SOAP Web Service」を選択。
作成されたSOAP Web Serviceを右クリックし、「Add Web Service Method」を選択する。
作成されたWeb Service Methodは普通のActionと同じように実装すればよい。
作成例
整数値を2つ受取り、それを足し合わせた結果を返す単純なCalculateSum Serviceを以下の通り実装する。
WSDLファイルを取得する
SOAPのサービスには通常、WSDLというサービスを定義するファイルがある。
このファイルがあると、.NETのツールでSOAPを利用するためのクライアントコードを自動生成できる。
OutSystems 11の場合、作成した「SOAP Web Service」を右クリックし、「Open Documentation」でドキュメントページを開き、
「Service Description」のリンク先から取得できる。リンク先をファイルに保存しておく。
SOAPのサービスをODCから呼ぶ
External Logicのプロジェクトを用意
External LogicをVisual Studio Codeで作成する > コマンドサマリに書いたコマンドで、SoapConsumeTestというプロジェクトをQiitaSamplesソリューションの下に用意する。
dotnet new sln -o QiitaSamples
cd .\QiitaSamples\
dotnet new classlib -o SoapConsumeSample --framework net6.0
dotnet sln add .\SoapConsumeSample\SoapConsumeSample.csproj
cd .\SoapConsumeSample\
dotnet add package OutSystems.ExternalLibraries.SDK
SOAPを利用するClassを用意する
dotnet-svcutilツールをインストール
ドキュメントは.NET Core 用 WCF dotnet-svcutil ツール
SOAPのメタデータを提供するWSDLファイルから、C#のクライアントコードを生成するツール。
dotnet tool install --global dotnet-svcutil
次のコマンドを使用してツールを呼び出せます。dotnet-svcutil
ツール 'dotnet-svcutil' (バージョン '2.1.0') が正常にインストールされました。
dotnet-svcutilコマンドでSOAPサービスクライアントコードを生成する
保存しておいたWSDLファイルをパラメータにdotnet-svcutilコマンドを実行すると、実行したパスにServiceReferenceフォルダが作成され、その下にSOAPサービスのクライアントコードがReference.csという名前で作成される。
dotnet-svcutil .\WebService1.xml
Microsoft (R) WCF Service Model Proxy Generation Tool for .Net Core platform
[Microsoft.Tools.ServiceModel.Svcutil、バージョン 2.1.0]
Copyright (c) Microsoft Corporation. All rights reserved.
このツールによって、ツールの改善を目的として使用法に関する情報が収集されます。この機能は、環境変数 "DOTNET_SVCUTIL_TELEMETRY_OPTOUT" を 1 に設定して無効にできます。
'C:\work\OutSystems\ODC\ExternalLogicTest\WebService1.xml' からメタデータを読み込もうとしています。
ファイルを生成しています...
C:\work\OutSystems\ODC\ExternalLogicTest\ServiceReference\Reference.cs
SOAPサービスクライアントはC#のファイルなので、プロジェクトの下に配置したい。
そこで、生成されたServiceReferenceフォルダをプロジェクトフォルダの下に移動しておく。
WSDLファイルは、URLで指定することもできる
dotnet-svcutil https://<ホスト>/<モジュール>/<SOAP Web Service>.asmx?WSDL
External Logicの実装
Interface定義例
属性の意味や書き方については参考リンクを参照。
using OutSystems.ExternalLibraries.SDK;
namespace SoapConsumeSample;
[OSInterface(Description = "ODCでSOAPのサービスを利用するサンプル")]
public interface ISoapConsumeSample
{
[OSAction(Description = "受け取った2つの値の合計を返す")]
public int CalculateSum(int Num1, int Num2);
}
クライアントを利用するのに必要なNuGetパッケージを追加する
VSCode上でTerminalを開き、以下のコマンドを入力する。
--Versionの指定をしないと、External Logicで使う.NET 6.0と互換性のないバージョンがインストールされてしまう。
dotnet add package System.ServiceModel.Primitives --version 6.2.0
dotnet add package System.ServiceModel.Http --version 6.2.0
Class定義例
↑で定義したinterfaceを実装するClassを用意する。
using OutSystems.ExternalLibraries.SDK;
using System.ServiceModel;
using System.Xml;
namespace SoapConsumeSample;
public class SoapConsumeSample : ISoapConsumeSample
{
// 1
#region ドキュメントの "Call the SOAP web service" 1と2で指定されていたコード(一部改変)
private static readonly string ENDPOINTADDRESS = "<SOAP Web ServiceのURL (.asmxで終わる) ";
private static readonly int TIMEOUT = 30;
private readonly BasicHttpBinding _binding;
private readonly EndpointAddress _address;
public SoapConsumeSample()
{
_binding = new BasicHttpBinding
{
SendTimeout = TimeSpan.FromSeconds(TIMEOUT),
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
AllowCookies = true,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
Security = new BasicHttpSecurity
{
Mode = BasicHttpSecurityMode.Transport
}
};
_address = new EndpointAddress(ENDPOINTADDRESS);
}
#endregion
// 3
public int CalculateSum(int Num1, int Num2)
{
return CalculateSumAsync(Num1, Num2).Result.Sum;
}
// 2
private async Task<CalculateSumResponse> CalculateSumAsync(int Num1, int Num2)
{
// dotnet-svcutil で作成したClass <SOAP Web Service名>SoapClientを使って非同期にSOAPサービスを呼び出し
using (var proxy = new WebService1SoapClient(_binding, _address))
{
// awaitをつけることで、CalculateSumAsyncの非同期呼び出しが終わるまでこのメソッドを止めている
var result = await proxy.CalculateSumAsync(Num1, Num2);
return result;
}
}
}
-
ドキュメントで指定されているメンバ変数とコンストラクタ
この部分は基本的にはそのままコピーでよい。ENDPOINTADDRESS変数の値だけは実際のURLに変更する必要がある。 -
SOAPサービスを直接呼ぶAsyncメソッド
dotnet-svcutilが生成するコードは非同期なので、接続先のWeb Service Method1つに対して1つ非同期のメソッド(asyncキーワードを付与し、Taskを返すメソッド)を作成する。
なお戻り値のTask<>の「<>」内は、呼び出すメソッドの戻り値として使われているものを指定する。
Reference.csのメソッドが以下のシグネチャであれば、Taskを使う。
「public System.Threading.Tasks.Task CalculateSumAsync(int Num1, int Num2)」 -
Action提供用メソッド
External LogicのActionに対する実装。
2.のメソッドを内部で呼び、その結果を返す。
非同期のメソッドを同期的に返すため、2.の戻り値に対し.Resultを適用している。
動作確認
PublishしてODC Portalに登録する
この部分は参考リンクの手順を参照。
ODCのAppから呼んでみた結果
OutSystems 11側のIntegration Logsで確認
Service CenterでMonitoring > IntegrationsでREST/SOAP実行ログを見られる。
確かに呼び出しされている。
参考リンク
External Logicの作成方法一般については以下を参照:
Visual Studio Codeを使ってExternal Logic向けのC#プロジェクトを作る手順については以下を参照:
OutSystemsの公式手順ドキュメント: