A C# handler is the method that Function Compute calls when your function is invoked. This topic explains the handler string format, valid method signatures, supported handler types (stream and POCO), serialization options, and how to handle HTTP trigger invocations.
If you want to use HTTP triggers or custom domain names to access functions, obtain request struct before you define HTTP responses. For more information, see Use an HTTP trigger to invoke a function.
Handler string format
C# handler strings follow this format:
Assembly::Namespace.ClassName::MethodName| Parameter | Description |
|---|---|
Assembly | Name of the assembly |
Namespace | Name of the namespace |
ClassName | Name of the class |
MethodName | Name of the method |
For example, if the name of the assembly is HelloFcApp, the handler is HelloFcApp::Example.HelloFC::StreamHandler.
Configure the handler string when you create or update a function in the Function Compute console. For more information, see Create an event function.
Valid handler signatures
A handler method can be either a static method or an instance method. All supported signatures are listed below. The IFcContext parameter is optional in all forms.
// 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);Function Compute waits for async methods to complete before returning.
Parameter types:
| Parameter | Accepted types |
|---|---|
ReturnType | void, System.IO.Stream, or any JSON-serializable object. A Stream return value is written directly to the response body; other types are JSON-serialized first. |
InputType | System.IO.Stream or any JSON-deserializable object |
IFcContext | The function context object. For more information, see Context. |
Event handlers
C# event handlers require the Aliyun.Serverless.Core NuGet package (version 1.0.1). Add it to your .csproj file:
<ItemGroup>
<PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
</ItemGroup>The package provides two handler types:
Stream handler — receives raw event data as a stream and writes results to an output stream.
POCO handler — uses plain old class objects (POCO) for typed input and output, with automatic JSON serialization.
Stream handler
A stream handler reads input from a Stream and returns a 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){}
}
}For the assembly HelloFcApp, the handler string for this example is:
HelloFcApp::Example.Hello::StreamHandlerKey elements:
| Element | Description |
|---|---|
Stream input | Input event data. Read from this stream in your handler. |
IFcContext context | (Optional) Context object providing request metadata and logging. |
Task<Stream> | Return type. The stream content is written directly to the response body. |
POCO handler
A POCO handler uses typed C# classes for input and output. Function Compute automatically serializes and deserializes these objects using 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){}
}
}For the assembly HelloFcApp, the handler string for this example is:
HelloFcApp::Example.Hello::PocoHandlerKey elements:
| Element | Description |
|---|---|
Product product | Input parameter of type Product. Deserialized from the event payload using JSON.Net. |
IFcContext context | (Optional) Context object. |
Product (return type) | Output serialized to JSON using JSON.Net and written to the response body. |
Serialization
POCO handlers use JSON.Net (Newtonsoft.Json) by default, provided by Aliyun.Serverless.Core. This covers most use cases without additional configuration — Function Compute automatically deserializes the incoming event into your input type and serializes the return value into the response body.
When to use a custom serializer: if you need to handle special types, custom naming conventions, or non-JSON formats, implement the IFcSerializer interface:
public interface IFcSerializer
{
T Deserialize<T>(Stream requestStream);
void Serialize<T>(T response, Stream responseStream);
}To use a custom serializer, apply the [FcSerializer] attribute to your handler method:
[FcSerializer(typeof(MySerialization))]
public Product PocoHandler(Product product, IFcContext context) { ... }Use an HTTP trigger to invoke a function
Sample code
The following example defines typed classes for an HTTP trigger request and response, reads the request body, and echoes it back.
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){}
}
}Prerequisites
Before you begin, ensure that you have:
A C# function created using the sample code above. For more information, see Create an event function and Configure an HTTP trigger
Invoke the function
Log on to the Function Compute console. In the left-side navigation pane, click Functions.
In the top navigation bar, select a region. On the Functions page, click the target function.
On the function details page, click the Triggers tab to get the public endpoint of the HTTP trigger.
Run the following command to invoke the function. Replace
https://test-python-ipgrwr****.cn-shanghai.fcapp.runwith your endpoint.curl -i "https://test-python-ipgrwr****.cn-shanghai.fcapp.run" -d 'Hello fc3.0'The expected response:
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.0ImportantIf Authentication Method is set to No Authentication, invoke with Postman or curl.
If Authentication Method is set to Signature Authentication or JWT Authentication, use the corresponding method. For more information, see Authentication.
Possible errors
This sample is designed for HTTP trigger or custom domain name invocation. If you click Test Function in the console and pass a plain string such as "Hello, FC!", the function returns a deserialization error because the input does not match the HTTPTriggerEvent format:
{
"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"
]
}Sample programs
The following GitHub repositories contain complete examples with build and deployment scripts:
dotnet3-blank-stream-event — event callbacks using the stream handler format
dotnet3-blank-poco-event — event callbacks using the POCO handler format