[ODC]External LogicのInput Parameterサイズには上限がある

OutSystems Developer Cloud (ODC) で、C#で作成したロジックを動作させるExternal Logicには、Input Parameterのサイズに上限がある。

その上限と対策がドキュメントに記載されているので、プログラムを書いて確認してみる。

# 環境情報
ODC Studio(Version 1.3.13)
Visual Studio Code(Version 1.86.0)

# ドキュメントから制約を確認する
2024/02/04時点の[英語版ドキュメント](https://success.outsystems.com/documentation/outsystems_developer_cloud/building_apps/extend_your_apps_with_external_logic_using_custom_code/external_libraries_sdk_readme/#use-with-large-binary-files)から

## 制約：Input Parameterのサイズは5.5MBまで
> Server actions exposed by external libraries don't support input larger than 5.5MB. If a large binary file is passed as input to a server action during an app's runtime, the end-user gets an error "Input payload is too large"

External Libraryが公開するServer ActionがInput Parameterとして受け取れるのはサイズで5.5MBまで。それを上回るデータを渡すと"Input payload is too large"というエラーを返す。

## 解決策：外部のURLからデータを受け取れるようにする
> 1. Expose the binary file in a REST API endpoint from your app and then implement logic in your custom code to consume the file from the endpoint.
> 2. Host the binary file on a file-sharing service and implement logic in your custom code to download the file from the URL.

要するに、External Logicのどこか外部のURLから必要なデータを受け取れるようにする、ということ。

# 動作確認：5.5MBを上回るデータを渡してみる
## サンプルコード：External Logic
External Logicを作成する手順は[ODCでC#を取り込んでみる（External Logic）](https://qiita.com/jyunji_watanabe/items/2698fb5a80b857875a48#interface%E3%81%AB%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)を参照。

Text型のデータを渡し、文字数をカウントして返すActionを作成する。実装は重要でない。5.5MBを上回るText型データを渡してエラーの発生を確認することを目的とする。

``` cs:IQiitaExternalLogicExample1.cs
using OutSystems.ExternalLibraries.SDK;

namespace QiitaExternalLogicExample1;

[OSInterface(Description = "This External Logic has some sample methods used in my Qiita articles.")]
public interface IQiitaExternalLogicExample1
{
    [OSAction(Description = "Count input characters and returns the number. This method is to show there is a input size limitation in my Qiita article.",
              ReturnName = "CharacterCount", ReturnDescription = "The number of characters in the Input Parameter.")]
    public int CountCharacters(string InputText);
}
```

``` cs:QiitaExternalLogicExample.cs
namespace QiitaExternalLogicExample1;

public class QiitaExternalLogicExample1 : IQiitaExternalLogicExample1
{
    public int CountCharacters(string InputText)
    {
        return InputText?.Length ?? 0;
    }
}
```

## 動作確認
以下のように、5,000,000Bytesと6,000,000BytesのファイルをEntityに保存しておき、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c9dc3f6a-fa1e-217f-8d8c-19600e8c7230.png)

テスト時に
1. EntityからBinary Dataを取り出す
1. BinaryData/BinaryDateToText ActionでText型に戻す
1. 作成したExternal LogicのActionに渡す

という手順で動作確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/5bcf41c9-13d7-056c-3fff-b0478b7bf681.png)

### 5,000,000Bytes (5MB弱) の場合
結果をClient Action内のMessageで表示した。

5.5MBという上限を下回るので、処理は無事に終了し、Messageで表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d92e1c06-d0c8-ab66-d9ca-4c520d9062bc.png)

### 6,000,000Bytes (5.5MB超) の場合
5.5MBを超えたため、エラーになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/16ea7649-aa9a-c714-b3a8-fab39510a605.png)

Traceを確認すると、以下のエラーが出ている。やはり、5.5MBのサイズ上限は効いているようだ。

> OS-BERT-ELR-61301 - Input payload is too large (5.72MB), maximum allowed is 5.5MB.

# 解決策確認：Expose REST APIで対象データを返し、External Logicから取りに行く
## Expose REST APIとして、6,000,000Bytesのデータを返すメソッドを作成する
動作確認なので、シンプルにText型を返すGETメソッドのREST API Methodを用意。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9248db99-31a1-acaf-0bcc-1790e933f613.png)

このメソッドは、Entityから6,000,000Bytesのバイナリデータを取り出し、BinaryDataToTextでTextに変換して返すだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/04a18694-a196-5689-d32f-94e74af2093e.png)

External Logicのロジックを以下の通り修正。url変数には、REST API Methodの実際のURLを設定する。

``` cs
var url = "";
using var httpClient = new HttpClient();
var response = httpClient.GetStringAsync(url).GetAwaiter().GetResult();
return response?.Length ?? 0;
```

## 動作確認
上記修正したExternal LogicのActionを使ってみると、無事に5.5MBを上回る値を受け取れている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/287f2738-930b-9055-f006-14a8274bcb90.png)