全部产品
云市场

C# 事件函数

更新时间:2020-03-31 14:35:05

在函数计算服务使用 C# 编程,需要定义一个 C# 函数作为入口。本文介绍了 C# 事件函数的结构和特点。

事件函数定义

当创建一个基于 C# 的函数时,需要指定一个 handler 方法,该方法在函数执行时被执行。这个handler 方法可以是 static 方法或 instance 方法,如果您想在 handler 方法中访问 IFcContext 对象,则需要将该方法中的第二个参数指定为 IFcContext 对象。事件函数支持的 handler 方法定义如下所示。

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

函数计算支持在使用 C# 编写的函数中应用 Async, 此时函数的执行会等待异步方法执行结束。

说明

  • ReturnType: 返回对象可以是 void (此时 Async Task 退化为 async Task)、 System.IO.Stream 对象、任何可以被 JSON 序列化和 JSON 反序列化的对象。如果是 Stream 对象,则该 Stream 内容直接在响应体返回。否则该返回对象被 JSON 序列化后在响应体返回。
  • InputType:输入参数可以是 System.IO.Stream 或任何可以被 JSON 序列化和 JSON 反序列化的对象。
  • IFcContext: 函数的 Context 对象。

在 context 中包含了以下信息。

参数 类型 描述
RequestId String 本次调用请求的唯一 ID,您可以把它记录下来在出现问题的时候方便查询。
FunctionParam Class 当前调用的函数的一些基本信息,例如函数名、函数入口、函数内存和超时时间。
Credentials Class 函数计算服务通过扮演您提供的服务角色获得的一组临时密钥 securityToken,每 15 分钟更新一次。您可以在函数代码中使用临时密钥去访问其他阿里云服务,例如 OSS,避免您将重要的身份凭证 AccessKey 写死在函数代码里。
ServiceMeta Class 当前调用的函数所在的 service 的信息,包含 service 的名字、接入的 SLS 的 logProject 和 logStore 信息、service 的版本信息、 qualifier 和 version_id。其中 qualifier 表示调用函数时指定的 service 版本或别名,version_id 表示实际调用的 service 版本。
Region String 当前调用的函数所在区域,例如 cn-shanghai。更多详情,请参见地域与可用区
AccountId String 当前调用函数用户的阿里云账号 ID。更多详情,请参见获取账号 ID

更多详情请参见 fc-dotnet-libs

Handler 方法示例

函数计算使用 C# 编写函数, 需要 Nuget 引入 Aliyun.Serverless.Core 包。

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 objects)对象同样也可以作为输入和输出。如果该 POCO 没有指定特定的 JSON Serializer 对象,则函数计算默认用 Json.Net 进行对象的 JSON Serialize 和 Deserialize。

  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 规范

命名格式

在创建函数时,您需要指定一个 handler 方法的字符串,用来告诉函数计算调用哪个方法,该字符串格式为AssemblyFileName::FullClassName::METHOD

参数说明

参数参数说明
AssemblyFileName函数所在的文件名
FullClassName函数所在类的全名
Method方法名

在上文 Handler 例子中,如果 Assembly 文件为 test_assembly, 则其 handler 字符串是test_assembly::FC.Examples.TestHandler::Echo

限制

  • Handler 参数格式严格按照上述定义,也就是说参数 1 为必须输入,参数 2 可选,但必须为 IFcContext
  • Handler 函数不支持 Generic Method
  • 输入输出参数必须为 Stream 或可 JSON 序列化。
  • Async 函数返回值 TaskT 必须为 Stream 或可 JSON 序列化的类。

Custom Serializer

函数计算针对 POCO Handler 提供了默认的基于 JSON .NET Serializer,如果默认的 Serializer 不能满足需求, 可以基于 Aliyun.Serverless.Core 中的接口 IFcSerializer 实现 Custom Serializer。

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

事件函数完整示例

下文演示了 C# 代码如何使用临时密钥向 OSS 的一个 Bucket 获取指定的一个对象。

  1. 创建一个 .net core 的 console 工程。

    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
  5. 使用 fcdotnetsample.zip 创建 runtime 为 dotnetcore2.1, handler 为 fcdotnetsample::fcdotnetsample.OSSFileHandler::GetOssFile 的函数。