C# ハンドラは、関数が呼び出されたときに Function Compute が呼び出すメソッドです。このトピックでは、ハンドラの文字列形式、有効なメソッドシグネチャ、サポートされているハンドラタイプ (ストリームと POCO)、シリアル化オプション、および HTTP トリガーの呼び出しを処理する方法について説明します。
HTTP トリガーまたはカスタムドメイン名を使用して関数にアクセスする場合は、HTTP レスポンスを定義する前にリクエスト構造体を取得してください。詳細については、「HTTP トリガーを使用した関数の呼び出し」をご参照ください。
ハンドラの文字列形式
C# ハンドラの文字列は、次の形式に従います:
Assembly::Namespace.ClassName::MethodName| パラメーター | 説明 |
|---|---|
Assembly | アセンブリの名前 |
Namespace | 名前空間の名前 |
ClassName | クラスの名前 |
MethodName | メソッドの名前 |
たとえば、アセンブリ名が HelloFcApp の場合、ハンドラは HelloFcApp::Example.HelloFC::StreamHandler です。
Function Computeコンソールで関数を作成または更新するときに、ハンドラ文字列を設定します。Function Computeコンソール。詳細については、「イベント関数の作成」をご参照ください。
有効なハンドラシグネチャ
ハンドラメソッドは、静的メソッドまたはインスタンスメソッドのいずれかです。サポートされているすべてのシグネチャを以下に示します。IFcContext パラメーターは、すべての形式でオプションです。
// 同期シグネチャ
ReturnType HandlerName(InputType input, IFcContext context);
ReturnType HandlerName(InputType input);
// 非同期シグネチャ
async Task<ReturnType> HandlerName(InputType input, IFcContext context);
async Task<ReturnType> HandlerName(InputType input);Function Compute は、非同期メソッドが完了するまで待機してから戻ります。
パラメーターの型:
| パラメーター | 受け入れられる型 |
|---|---|
ReturnType | void、System.IO.Stream、または任意の JSON シリアル化可能なオブジェクト。Stream の戻り値はレスポンスボディに直接書き込まれます。他の型は、最初に JSON シリアル化されます。 |
InputType | System.IO.Stream または任意の JSON 逆シリアル化可能なオブジェクト |
IFcContext | 関数コンテキストオブジェクト。詳細については、「コンテキスト」をご参照ください。 |
イベントハンドラ
C# イベントハンドラには、Aliyun.Serverless.Core NuGet パッケージ (バージョン 1.0.1) が必要です。これを .csproj ファイルに追加します:
<ItemGroup>
<PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
</ItemGroup>このパッケージは、2 種類のハンドラを提供します:
ストリームハンドラ — 生のイベントデータをストリームとして受信し、結果を出力ストリームに書き込みます。
POCO ハンドラ — 型指定された入力と出力に POCO (単純な従来のクラスオブジェクト) を使用し、JSON シリアル化を自動的に行います。
ストリームハンドラ
ストリームハンドラは、Stream から入力を読み取り、Stream を返します。
using System.IO;
using System.Threading.Tasks;
using Aliyun.Serverless.Core;
using Microsoft.Extensions.Logging;
namespace Example
{
public class Hello
{
public async Task<Stream> StreamHandler(Stream input, IFcContext context)
{
IFcLogger logger = context.Logger;
logger.LogInformation("Handle request: {0}", context.RequestId);
MemoryStream copy = new MemoryStream();
await input.CopyToAsync(copy);
copy.Seek(0, SeekOrigin.Begin);
return copy;
}
static void Main(string[] args){}
}
}アセンブリ HelloFcApp の場合、この例のハンドラ文字列は次のようになります:
HelloFcApp::Example.Hello::StreamHandler主要な要素:
| 要素 | 説明 |
|---|---|
Stream input | 入力イベントデータ。ハンドラでこのストリームから読み取ります。 |
IFcContext context | (オプション) リクエストのメタデータとロギングを提供するコンテキストオブジェクト。 |
Task<Stream> | 戻り値の型。ストリームのコンテンツはレスポンスボディに直接書き込まれます。 |
POCO ハンドラ
POCO ハンドラは、入力と出力に型指定された C# クラスを使用します。Function Compute は、JSON.Net (Newtonsoft.Json) を使用してこれらのオブジェクトを自動的にシリアル化および逆シリアル化します。
using Aliyun.Serverless.Core;
using Microsoft.Extensions.Logging;
namespace Example
{
public class Hello
{
public class Product
{
public string Id { get; set; }
public string Description { get; set; }
}
// オプション:カスタムシリアライザクラスを指定します。
// 省略した場合、デフォルトの JSON.Net シリアライザが使用されます。
// [FcSerializer(typeof(MySerialization))]
public Product PocoHandler(Product product, IFcContext context)
{
string Id = product.Id;
string Description = product.Description;
context.Logger.LogInformation("Id {0}, Description {1}", Id, Description);
return product;
}
static void Main(string[] args){}
}
}アセンブリ HelloFcApp の場合、この例のハンドラ文字列は次のようになります:
HelloFcApp::Example.Hello::PocoHandler主要な要素:
| 要素 | 説明 |
|---|---|
Product product | 型が Product の入力パラメーター。JSON.Net を使用してイベントペイロードから逆シリアル化されます。 |
IFcContext context | (オプション) コンテキストオブジェクト。 |
Product (戻り値の型) | JSON.Net を使用して JSON にシリアル化され、レスポンスボディに書き込まれる出力。 |
シリアル化
POCO ハンドラは、Aliyun.Serverless.Core によって提供される JSON.Net (Newtonsoft.Json) をデフォルトで使用します。これにより、追加の設定なしでほとんどのユースケースに対応できます。Function Compute は、受信イベントを入力タイプに自動的に逆シリアル化し、戻り値をレスポンスボディにシリアル化します。
カスタムシリアライザを使用する場合:特別な型、カスタムの命名規則、または非 JSON 形式を処理する必要がある場合は、IFcSerializer インターフェイスを実装します:
public interface IFcSerializer
{
T Deserialize<T>(Stream requestStream);
void Serialize<T>(T response, Stream responseStream);
}カスタムシリアライザを使用するには、ハンドラメソッドに [FcSerializer] 属性を適用します:
[FcSerializer(typeof(MySerialization))]
public Product PocoHandler(Product product, IFcContext context) { ... }HTTP トリガーを使用した関数の呼び出し
サンプルコード
次の例では、HTTP トリガーのリクエストとレスポンスの型指定されたクラスを定義し、リクエストボディを読み取って、それをエコーバックします。
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using Aliyun.Serverless.Core;
using Microsoft.Extensions.Logging;
namespace Example
{
public class Hello
{
public class HTTPTriggerEvent
{
public string Version { get; set; }
public string RawPath { get; set; }
public string Body { get; set; }
public bool IsBase64Encoded { get; set; }
public RequestContext RequestContext { get; set; }
public Dictionary<string, string> Headers { get; set; }
public Dictionary<string, string> QueryParameters { get; set; }
public override string ToString()
{
return JsonSerializer.Serialize(this);
}
}
public class RequestContext
{
public string AccountId { get; set; }
public string DomainName { get; set; }
public string DomainPrefix { get; set; }
public string RequestId { get; set; }
public string Time { get; set; }
public string TimeEpoch { get; set; }
public Dictionary<string, string> Http { get; set; }
}
public class HTTPTriggerResponse
{
public int StatusCode { get; set; }
public Dictionary<string, string> Headers { get; set; }
public bool IsBase64Encoded { get; set; }
public string Body { get; set; }
}
public HTTPTriggerResponse PocoHandler(HTTPTriggerEvent input, IFcContext context)
{
context.Logger.LogInformation("receive event: {0}", input.ToString());
string requestBody = input.Body;
if (input.IsBase64Encoded)
{
byte[] decodedBytes = Convert.FromBase64String(input.Body);
requestBody = Encoding.UTF8.GetString(decodedBytes);
}
return new HTTPTriggerResponse
{
StatusCode = 200,
IsBase64Encoded = false,
Body = requestBody
};
}
static void Main(string[] args){}
}
}前提条件
開始する前に、次のものが揃っていることを確認してください:
上記のサンプルコードを使用して作成された C# 関数。詳細については、「イベント関数の作成」および「HTTP トリガーの設定」をご参照ください。
関数の呼び出し
Function Compute コンソールにログインします。左側のナビゲーションウィンドウで、[関数] をクリックします。
上部のナビゲーションバーで、リージョンを選択します。[関数] ページで、対象の関数をクリックします。
関数の詳細ページで、[トリガー] タブをクリックして、HTTP トリガーのパブリックエンドポイントを取得します。
次のコマンドを実行して関数を呼び出します。
https://test-python-ipgrwr****.cn-shanghai.fcapp.runをご自身のエンドポイントに置き換えてください。curl -i "https://test-python-ipgrwr****.cn-shanghai.fcapp.run" -d 'Hello fc3.0'期待されるレスポンス:
HTTP/1.1 200 OK Content-Disposition: attachment Content-Length: 12 Content-Type: application/json X-Fc-Request-Id: 1-64f7449a-127fbe39cd7681596e33ebad Date: Tue, 05 Sep 2023 15:09:14 GMT Hello fc3.0重要[認証方法] が [認証なし] に設定されている場合は、Postman または curl で呼び出します。
[認証方法] が [署名認証] または [JWT 認証] に設定されている場合は、対応する方法を使用してください。詳細については、「認証」をご参照ください。
考えられるエラー
このサンプルは、HTTP トリガーまたはカスタムドメイン名による呼び出し用に設計されています。コンソールで [関数のテスト] をクリックし、"Hello, FC!" のようなプレーンテキスト文字列を渡すと、入力が HTTPTriggerEvent 形式と一致しないため、関数は逆シリアル化エラーを返します:
{
"errorMessage": "Unexpected character encountered while parsing value: H. Path '', line 0, position 0.",
"errorType": "Newtonsoft.Json.JsonReaderException",
"stackTrace": [
" at Newtonsoft.Json.JsonTextReader.ParseValue()",
" at Newtonsoft.Json.JsonReader.ReadAndMoveToContent()",
" at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)",
" at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)",
" at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)",
" at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)",
" at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)",
" at Aliyun.Serverless.Core.JsonSerializer.Deserialize[T](Stream requestStream) in /dotnetcore/Libraries/src/Aliyun.Serverless.Core.Impl/JsonSerializer.cs:line 95"
]
}サンプルプログラム
次の GitHub リポジトリには、ビルドおよびデプロイスクリプトを含む完全なサンプルが含まれています:
dotnet3-blank-stream-event — ストリームハンドラ形式を使用したイベントコールバック
dotnet3-blank-poco-event — POCO ハンドラ形式を使用したイベントコールバック