Um handler em C# é o método que o Function Compute chama ao invocar sua função. Este tópico explica o formato da string do handler, assinaturas de método válidas, tipos de handler compatíveis (stream e POCO), opções de serialização e como lidar com invocações de gatilho HTTP.
Para usar gatilhos HTTP ou nomes de domínio personalizados no acesso às funções, obtenha a struct de requisição antes de definir as respostas HTTP. Para mais informações, consulte Usar um gatilho HTTP para invocar uma função.
Formato da string do handler
As strings de handler em C# seguem este formato:
Assembly::Namespace.ClassName::MethodName
|
Parâmetro |
Descrição |
|
|
Nome do assembly |
|
|
Nome do namespace |
|
|
Nome da classe |
|
|
Nome do método |
Por exemplo, se o nome do assembly for HelloFcApp, o handler será HelloFcApp::Example.HelloFC::StreamHandler.
Configure a string do handler ao criar ou atualizar uma função no console do Function Compute. Para mais informações, consulte Criar uma função de evento.
Assinaturas válidas de handler
O método handler pode ser estático ou de instância. Todas as assinaturas compatíveis estão listadas abaixo. O parâmetro IFcContext é opcional em todas as formas.
// Synchronous signatures
ReturnType HandlerName(InputType input, IFcContext context);
ReturnType HandlerName(InputType input);
// Asynchronous signatures
async Task<ReturnType> HandlerName(InputType input, IFcContext context);
async Task<ReturnType> HandlerName(InputType input);
O Function Compute aguarda a conclusão dos métodos assíncronos antes de retornar.
Tipos de parâmetros:
|
Parâmetro |
Tipos aceitos |
|
|
|
|
|
|
|
|
Objeto de contexto da função. Para mais informações, consulte Contexto. |
Handlers de eventos
Os handlers de eventos em C# exigem o pacote NuGet Aliyun.Serverless.Core (versão 1.0.1). Adicione-o ao arquivo .csproj:
<ItemGroup>
<PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
</ItemGroup>
Esse pacote fornece dois tipos de handler:
Stream handler: recebe dados brutos do evento como um stream e grava os resultados em um stream de saída.
POCO handler: utiliza objetos de classes simples (POCO) para entrada e saída tipadas, com serialização JSON automática.
Stream handler
Um stream handler lê a entrada de um Stream e retorna um 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){}
}
}
Para o assembly HelloFcApp, a string do handler neste exemplo é:
HelloFcApp::Example.Hello::StreamHandler
Elementos principais:
|
Elemento |
Descrição |
|
|
Dados do evento de entrada. Leia deste stream no seu handler. |
|
|
(Opcional) Objeto de contexto que fornece metadados da requisição e recursos de log. |
|
|
Tipo de retorno. O conteúdo do stream é gravado diretamente no corpo da resposta. |
POCO handler
Um POCO handler usa classes C# tipadas para entrada e saída. O Function Compute serializa e desserializa automaticamente esses objetos usando 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; }
}
// Optional: specify a custom serializer class.
// If omitted, the default JSON.Net serializer is used.
// [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){}
}
}
Para o assembly HelloFcApp, a string do handler neste exemplo é:
HelloFcApp::Example.Hello::PocoHandler
Elementos principais:
|
Elemento |
Descrição |
|
|
Parâmetro de entrada do tipo |
|
|
(Opcional) Objeto de contexto. |
|
|
Saída serializada para JSON usando JSON.Net e gravada no corpo da resposta. |
Serialização
Os POCO handlers usam JSON.Net (Newtonsoft.Json) por padrão, fornecido pelo pacote Aliyun.Serverless.Core. Isso atende à maioria dos casos de uso sem configuração adicional. O Function Compute desserializa automaticamente o evento recebido para o tipo de entrada e serializa o valor de retorno no corpo da resposta.
Quando usar um serializador personalizado: para lidar com tipos especiais, convenções de nomenclatura personalizadas ou formatos não JSON, implemente a interface IFcSerializer:
public interface IFcSerializer
{
T Deserialize<T>(Stream requestStream);
void Serialize<T>(T response, Stream responseStream);
}
Para usar um serializador personalizado, aplique o atributo [FcSerializer] ao método handler:
[FcSerializer(typeof(MySerialization))]
public Product PocoHandler(Product product, IFcContext context) { ... }
Usar um gatilho HTTP para invocar uma função
Código de exemplo
O exemplo a seguir define classes tipadas para requisição e resposta de um gatilho HTTP, lê o corpo da requisição e o devolve como eco.
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){}
}
}
Pré-requisitos
Antes de começar, verifique se você tem:
Uma função C# criada com o código de exemplo acima. Para mais informações, consulte Criar uma função de evento e Configurar um gatilho HTTP
Invocar a função
Faça login no console do Function Compute. No painel de navegação à esquerda, clique em Functions.
Na barra de navegação superior, selecione uma região. Na página Functions, clique na função desejada.
Na página de detalhes da função, clique na aba Triggers para obter o endpoint público do gatilho HTTP.
-
Execute o comando a seguir para invocar a função. Substitua
https://test-python-ipgrwr****.cn-shanghai.fcapp.runpelo seu endpoint.curl -i "https://test-python-ipgrwr****.cn-shanghai.fcapp.run" -d 'Hello fc3.0'Resposta esperada:
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.0ImportanteSe o Authentication Method estiver definido como No Authentication, invoque a função com Postman ou curl.
Caso o Authentication Method esteja configurado como Signature Authentication ou JWT Authentication, use o método correspondente. Para mais informações, consulte Autenticação.
Possíveis erros
Este exemplo foi projetado para invocação via gatilho HTTP ou nome de domínio personalizado. Se você clicar em Test Function no console e passar uma string simples como "Hello, FC!", a função retornará um erro de desserialização porque a entrada não corresponde ao formato 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"
]
}
Programas de exemplo
Os repositórios do GitHub a seguir contêm exemplos completos com scripts de build e implantação:
dotnet3-blank-stream-event: callbacks de eventos com o formato stream handler
dotnet3-blank-poco-event: callbacks de eventos com o formato POCO handler