edit-icon download-icon

C# ハンドラ

最終更新日: May 07, 2019

Function Compute で C# を使用するには、まず C# で書かれた関数をハンドラとして定義する必要があります。このトピックでは、使用できる C# ハンドラとその定義について説明します。

概要

現在、C# ランタイム (.NET Core 2.1) は共通ハンドラと HTTP トリガーハンドラの 2 種類のハンドラをサポートしています。HTTP トリガーを設定したらハンドラの形式が異なります。それは HTTP リクエストを簡単に処理するためです。

共通ハンドラ

ハンドラの定義

C# 関数を作成する際に、関数と共に実行される Handler メソッドを指定する必要があります。この Handler メソッドは、static メソッドまたは instance メソッドにすることができます。このメソッドで IFcContext オブジェクトにアクセスするには、このメソッドの 2 番目のパラメーターとして IFcContext オブジェクト を指定できます。サポートしている Handler メソッドは次のように定義されています。

  1. ReturnType HandlerName(InputType input, IFcContext context); // IFcContext included
  2. ReturnType HandlerName(InputType input); // IFcContext not included
  3. Async Task<ReturnType> HandlerName(InputType input, IFcContext context);
  4. Async Task<ReturnType> HandlerName(InputType input);

Function Compute は、C# で記述された関数で Async の使用をサポートしています。この場合、関数の実行は非同期メソッドの実行の終了を待ちます。

上記の定義は、以下のとおりです。

  • ReturnType: 返されるオブジェクトです。voidSystem.IO.Stream オブジェクト、あるいは 任意の JSON シリアライズオブジェクトまたはデシリアライズオブジェクト になります。void が返されると、Async Task は、async Task にデグレードされます。Stream オブジェクト が返される場合、Stream の内容はレスポンスボディで返されます。それ以外の場合、返されるオブジェクトは JSON でシリアル化され、レスポンスボディで返されます。

  • InputType: 入力パラメーターです。System.IO.Stream または 任意の JSON シリアライズオブジェクトまたはデシリアライズオブジェクト になります。

  • IFcContext: 関数のコンテキストオブジェクトです。以下の情報が含まれます。

パラメーター 説明
RequestId String 現在のコールリクエストの GUID。通常、障害検出または履歴コールカウント中に使用されます。
FunctionParam Class 現在呼び出されている関数に関する基本情報。 (関数名、ハンドラ、メモリ、タイムアウト期間など)
Credentials Class Function Compute が、提供されたサービスロールを行うことで取得される一時的な SecurityToken。SecurityToken は 15 分ごとに更新されます。SecurityToken を使用して、OSS など他の Alibaba Cloud サービスにアクセスできます。これにより、関数コードで AccessKey のハードコーディングを防ぎます。
ServiceMeta Class 現在呼び出されている関数が属するサービスに関する情報。 Log Service のサービス名、アクセスされた Logproject や Logstore、および修飾子や version_id などのサービスのバージョンを含みます。修飾子は、関数が呼び出されるときに指定されるサービスのバージョン、またはエイリアスを示し、version_id は実際に呼び出されるサービスのバージョンを示します。
Region String cn-shanghai など、現在呼び出されている関数が配置されているリージョン。詳細については、「リージョンとゾーン」 をご参照ください。
AccountId String 現在の関数の呼び出し元の Alibaba Cloud アカウント ID。詳細については、「アカウント ID の取得」 をご参照ください。

詳しくは 「fc-dotnet-libs」 をご参照ください。

Handler メソッドの例

Function Compute を使用して C# で関数を記述する際、 Aliyun.Serverless.Core パッケージは NuGet を通して導入する必要があります。

Stream Handler

次のメソッドでは、ユーザーリクエストからの入力をそのまま返します。

  1. using System.IO;
  2. using System.Threading.Tasks;
  3. using Aliyun.Serverless.Core;
  4. using Microsoft.Extensions.Logging;
  5. namespace FC.Examples
  6. {
  7. public class TestHandler
  8. {
  9. public async Task<Stream> Echo(Stream input, IFcContext context)
  10. {
  11. ILogger logger = context.Logger;
  12. logger.LogInformation("Handle request: {0}", context.RequestId);
  13. MemoryStream copy = new MemoryStream();
  14. await input.CopyToAsync(copy);
  15. copy.Seek(0, SeekOrigin.Begin);
  16. return copy;
  17. }
  18. }
  19. }

POCO Handler

Stream オブジェクトに加えて、POCO (Plain Old CLR Object) も入力および出力パラメーターとして使用できます。POCO が JSON シリアル化オブジェクトを指定しない場合、Function Compute はデフォルト Json.Net を使用して、JSON 形式のオブジェクトをシリアライズおよびデシリアライズします。

  1. using Microsoft.Extensions.Logging;
  2. namespace FC.Examples
  3. {
  4. public class TestHandler
  5. {
  6. public class Product
  7. {
  8. public string Id { get; set; }
  9. public string Description { get; set; }
  10. }
  11. // optional serializer class, if it’s not specified, the default serializer (based on JSON.Net) will be used.
  12. // [FcSerializer(typeof(MySerialization))]
  13. public Product Echo(Product product, IFcContext context)
  14. {
  15. string Id = product.Id;
  16. string Description = product.Description;
  17. context.Logger.LogInformation("Id {0}, Description {1}", Id, Description);
  18. return product;
  19. }
  20. }
  21. }

Handler の指定

ハンドラの署名

関数を作成するときは、呼び出すメソッドを見つける方法を Function Compute に指示するために、文字列形式で handler メソッドを指定する必要があります。文字列の形式は次のとおりです。

AssemblyFileName::FullClassName::METHOD

この内、

  • AssemblyFileName は関数がある Assembly のファイル名です。 (.dll は省略されます)

  • FullClassName は関数が属するクラスのフルネーム、つまり、Namespace.ClassName です。

  • Method は呼び出されるメソッドの名前です。

上記の Handler の例で、Assembly ファイルの名前が test_assembly の場合、 handler の文字列は以下のようになります。

test_assembly::FC.Examples.TestHandler::Echo

制限事項

  • Handler パラメーターの形式は前述の定義に従います。つまり、パラメーター 1 は必須ですが、パラメーター 2 はオプションで、 IFcContext は定数です。

  • Handler 関数は、Generic Method をサポートしていません。

  • 入力パラメーターと出力パラメーターは Stream オブジェクトにするか、JSON 形式でシリアル化 する必要があります。

  • Async 関数は Task を返します。T は Stream オブジェクトか、あるいは JSON 形式でシリアル化 できるクラスでなければなりません。

Custom Serializer

POCO ハンドラの場合、Function Compute はデフォルトで、JSON . NET シリアライザを提供しています。デフォルトのシリアライザが要件を満たさない場合は、 Aliyun.Serverless.CoreIFcSerializer インターフェイスに基づいてカスタムシリアライザを実装することができます。

  1. public interface IFcSerializer
  2. {
  3. T Deserialize<T>(Stream requestStream);
  4. void Serialize<T>(T response, Stream responseStream);
  5. }

共通ハンドラの動作例

SecurityToken は、リクエスト者の身元と許可を検証するために使用されます。OSS などの他の Alibaba Cloud サービスにアクセスするときは、SecurityToken を指定する必要があります。次の C# サンプルコードでは、SecurityToken を使用して OSS バケットから指定されたオブジェクトを取得しています。

  1. .NET Core コンソールプロジェクトを作成します。

    1. [songluo@~/tmp]# mkdir fcdotnetsample
    2. [songluo@~/tmp]# cd fcdotnetsample
    3. [songluo@~/tmp/fcdotnetsample]# dotnet new console
  2. 以下のパッケージを fcdotnetsample.csproj に追加します。

    1. <ItemGroup>
    2. <PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
    3. <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.9.1" />
    4. </ItemGroup>
  3. Program.cs を編集します。

    1. using System;
    2. using System.IO;
    3. using Aliyun.OSS;
    4. using Aliyun.Serverless.Core;
    5. namespace fcdotnetsample
    6. {
    7. class Program
    8. {
    9. static void Main(string[] args)
    10. {
    11. Console.WriteLine("Hello World!");
    12. }
    13. }
    14. public class OssFileHandlerRequest
    15. {
    16. public string Bucket;
    17. public string Key;
    18. public string Endpoint;
    19. }
    20. public class OSSFileHandler
    21. {
    22. public Stream GetOssFile(OssFileHandlerRequest req, IFcContext context)
    23. {
    24. if (req == null)
    25. {
    26. throw new ArgumentNullException(nameof(req));
    27. }
    28. if (context == null || context.Credentials == null)
    29. {
    30. throw new ArgumentNullException(nameof(context));
    31. }
    32. OssClient ossClient = new OssClient(req.Endpoint, context.Credentials.AccessKeyId, context.Credentials.AccessKeySecret, context.Credentials.SecurityToken);
    33. OssObject obj = ossClient.GetObject(req.Bucket, req.Key);
    34. return obj.Content;
    35. }
    36. }
    37. }
  4. プロジェクトを公開し、ターゲットファイルを .zip パッケージに圧縮します。

    1. [songluo@~/tmp/fcdotnetsample]# dotnet publish -c Release
    2. Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
    3. Copyright (C) Microsoft Corporation. All rights reserved.
    4. Restore completed in 47.9 ms for /Users/songluo/tmp/fcdotnetsample/fcdotnetsample.csproj.
    5. fcdotnetsample -> /Users/songluo/tmp/fcdotnetsample/bin/Release/netcoreapp2.1/fcdotnetsample.dll
    6. fcdotnetsample -> /Users/songluo/tmp/fcdotnetsample/bin/Release/netcoreapp2.1/publish/
    7. [songluo@~/tmp/fcdotnetsample]# cd /Users/songluo/tmp/fcdotnetsample/bin/Release/netcoreapp2.1/publish/
    8. [songluo@~/tmp/fcdotnetsample/bin/Release/netcoreapp2.1/publish]# zip -r fcdotnetsample.zip *
    9. adding: Aliyun.OSS.Core.dll (deflated 60%)
    10. adding: Aliyun.Serverless.Core.dll (deflated 59%)
    11. adding: Microsoft.Extensions.Logging.Abstractions.dll (deflated 53%)
    12. adding: fcdotnetsample.deps.json (deflated 73%)
    13. adding: fcdotnetsample.dll (deflated 57%)
    14. adding: fcdotnetsample.pdb (deflated 27%)
    15. adding: fcdotnetsample.runtimeconfig.json (deflated 23%)
    16. [songluo@~/tmp/fcdotnetsample/bin/Release/netcoreapp2.1/publish]# ls -ll fcdotnetsample.zip
    17. -rw-r--r-- 1 songluo staff 130276 Mar 14 17:48 fcdotnetsample.zip

fcdotnetsample.zip を使用して、ランタイム .NET Core 2.1 とハンドラ fcdotnetsample::fcdotnetsample.OSSFileHandler::GetOssFile で関数を作成します。

Initializer ハンドラ

Function Compute は初期化のための Init メソッドを提供しています。バックグラウンドコンテナーが開始されると、Init メソッドが自動的に呼び出されます。各バックグラウンドコンテナーは一度だけ呼び出されます。

init メソッドの定義

  1. public void Init(); // No context objects
  2. public void Init(IFcContext context); // Include context objects
  3. public static void Init(); // No context objects
  4. public static void Init(IFcContext context); // Include context objects

Initializer 形式

  • MyInitializer は Initializer 関数が追加される際に “initializer” フィールドをマッピングする必要があります。たとえば、関数が作成される際に fcdotnetsample::fcdotnetsample.TestHandler::MyInitializer が Initializer ハンドラとして指定されている場合、初期化設定後、Function Compute は、最初に fcdotnetsample.TestHandler で定義された MyInitializer 関数をロードします。

Initializer 特徴

  • IFcContext の FunctionParam の FunctionInitializerInitializationTimeout は、 Initializer 用に設計されており、Initializer の使用中に関数が作成されると、ユーザー定義の値に設定されます。それ以外の場合は空になり、無効になります。
  • 値は返されません。関数に追加された Return 操作は無効です。

HTTP トリガーハンドラ

HTTP トリガーを持つハンドラは、他のトリガー必須ハンドラとは異なり、次のように定義されています。

C# で HTTP トリガーを使って関数を記述する場合、 Aliyun.Serverless.CoreAliyun.Serverless.Core.Http パッケージは NuGet を通して導入される必要があります。

  1. using System.Threading.Tasks;
  2. using Microsoft.AspNetCore.Hosting;
  3. using Microsoft.AspNetCore.Http;
  4. using Aliyun.Serverless.Core;
  5. using Aliyun.Serverless.Core.Http;
  6. namespace MySpace.TestHandlers
  7. {
  8. public class SingleHttpHandler : FcHttpEntrypoint
  9. {
  10. protected override void Init(IWebHostBuilder builder)
  11. { }
  12. public override async Task<HttpResponse> HandleRequest(HttpRequest request, HttpResponse response, IFcContext fcContext)
  13. {
  14. response.StatusCode = 200;
  15. response.ContentType = "text/plain";
  16. await response.WriteAsync("hello world");
  17. return response;
  18. }
  19. }
  20. }

入力パラメーター

説明

HTTP トリガーを持つ C# で記述された関数は、 Aliyun.Serverless.Core.HttpFcHttpEntrypoint を継承しなければなりません。Init 関数をオーバーライドする必要があります。HandleRequest はハンドラであり、必要に応じてオーバーライドすることができます。

  • Single function: HandleRequest カスタマイズを論理的に処理する HandleRequest をオーバーライドするために使用されます。

  • Asp.net core application: Init 関数だけがオーバーライドされます。

次の例では FcHttpEntrypoint の使い方を示しています。

HTTP トリガーハンドラの例

Single 関数の例

次の例では、HTTP トリガーを持つハンドラの HttpRequest および HttpResponse を使用する方法を示しています。

  1. using System.IO;
  2. using System.Threading.Tasks;
  3. using Microsoft.AspNetCore.Hosting;
  4. using Microsoft.AspNetCore.Http;
  5. using Aliyun.Serverless.Core;
  6. using Aliyun.Serverless.Core.Http;
  7. using Microsoft.Extensions.Logging;
  8. namespace MySpace.TestHandlers
  9. {
  10. public class SingleHttpHandler : FcHttpEntrypoint
  11. {
  12. protected override void Init(IWebHostBuilder builder)
  13. {
  14. }
  15. public override async Task<HttpResponse> HandleRequest(HttpRequest request, HttpResponse response, IFcContext fcContext)
  16. {
  17. string method = request.Method;
  18. string relativePath = request.Path.Value;
  19. fcContext.Logger.LogInformation("method = {0}; requestPath = {1}", method, relativePath);
  20. StreamReader sr = new StreamReader(request.Body);
  21. string requestBody = sr.ReadToEnd();
  22. fcContext.Logger.LogInformation("requestBody = {}", requestBody);
  23. // process request.Headers
  24. response.StatusCode = 200;
  25. response.ContentType = "text/plain";
  26. response.Headers.Add("customheader", "v1");
  27. await response.WriteAsync("hello world");
  28. return response;
  29. }
  30. }
  31. }

Asp.net core application の例

  1. using System;
  2. using Aliyun.Serverless.Core.Http;
  3. using Microsoft.AspNetCore.Hosting;
  4. namespace MySpace.TestWebApi
  5. {
  6. public class FcRemoteEntrypoint : FcHttpEntrypoint
  7. {
  8. protected override void Init(IWebHostBuilder builder)
  9. {
  10. builder
  11. .UseStartup<Startup>();
  12. }
  13. }
  14. }

操作手順

  1. asp.net core の webapi プロジェクトを作成します。

    1. [songluo@~/tmp]# mkdir fcaspdotnetsample
    2. [songluo@~/tmp]# cd fcaspdotnetsample
    3. [songluo@~/tmp/fcaspdotnetsample]# dotnet new webapi
  2. 以下のパッケージを fcaspdotnetsample.csproj に追加します。

    1. <ItemGroup>
    2. <PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
    3. <PackageReference Include="Aliyun.Serverless.Core.Http" Version="1.0.2" />
    4. </ItemGroup>
  3. Asp.net core application のサンプルコードを含む FcRemoteEntrypoint.cs という名前のファイルを作成します。

  4. プロジェクトを公開し、ターゲットファイルを .zip パッケージに圧縮します。

    1. [songluo@~/tmp/fcaspdotnetsample]# dotnet publish -c Release
    2. Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
    3. Copyright (C) Microsoft Corporation. All rights reserved.
    4. Restore completed in 88.39 ms for /Users/songluo/tmp/fcaspdotnetsample/fcaspdotnetsample.csproj.
    5. fcaspdotnetsample -> /Users/songluo/tmp/fcaspdotnetsample/bin/Release/netcoreapp2.1/fcaspdotnetsample.dll
    6. fcaspdotnetsample -> /Users/songluo/tmp/fcaspdotnetsample/bin/Release/netcoreapp2.1/publish/
    7. [songluo@~/tmp/fcaspdotnetsample]# cd /Users/songluo/tmp/fcaspdotnetsample/bin/Release/netcoreapp2.1/publish/
    8. [songluo@~/tmp/fcaspdotnetsample/bin/Release/netcoreapp2.1/publish]# zip -r fcaspdotnetsample.zip *
    9. adding: appsettings.Development.json (deflated 40%)
    10. adding: appsettings.json (deflated 30%)
    11. adding: fcaspdotnetsample.deps.json (deflated 85%)
    12. adding: fcaspdotnetsample.dll (deflated 61%)
    13. adding: fcaspdotnetsample.pdb (deflated 40%)
    14. adding: fcaspdotnetsample.runtimeconfig.json (deflated 31%)
    15. adding: web.config (deflated 40%)
    16. [songluo@~/tmp/fcaspdotnetsample/bin/Release/netcoreapp2.1/publish]# ls -ll fcaspdotnetsample.zip
    17. -rw-r--r-- 1 songluo staff 39101 Mar 15 09:47 fcaspdotnetsample.zip

fcaspdotnetsample.zip を使用して、ランタイム .NET Core 2.1 とfcaspdotnetsample::MySpace.TestWebApi.FcRemoteEntrypoint::HandleRequest ハンドラで関数を作成します。

Single 関数を使用している場合は、共通ハンドラの完了動作例の手順に従って、コンソールプロジェクトと FcRemoteEntrypoint.cs を作成し、そのコードを Single 関数のサンプルコードと置き換えてください。

HTTP トリガーハンドラの制限事項

リクエストの制限事項

HTTP トリガーを持つハンドラのリクエストが以下の制限を超えると、ステータスコード 400 とエラーコード InvalidArgument がスローされます。

パラメーター 制限事項 HTTP ステータスコード エラーコード
headers ヘッダー内のすべてのキーと値のペアのサイズは 4 KB を超えることはできません。 400 InvalidArgument
path パスとすべてのクエリパラメーターのサイズは 4 KB を超えることはできません。
body HTTP リクエストボディのサイズは 6 MB を超えることはできません。

レスポンスの制限事項

HTTP トリガーを持つハンドラのレスポンスが以下の制限を超えると、 502 ステータスコードと BadResponse エラーコードがスローされます。

パラメーター 制限事項 HTTP ステータスコード エラーコード
headers ヘッダー内のすべてのキーと値のペアのサイズは 4 KB を超えることはできません。 502 BadResponse
body HTTP レスポンスボディのサイズは 6 MB を超えることはできません。

HTTP トリガーの詳細については、「HTTP トリガー」 をご参照ください。

参考文献

C# ランタイムの詳細については、「C# ランタイム」 をご参照ください。