您可以使用C#請求處理常式響應接收到的事件並執行相應的商務邏輯。本文介紹C#請求處理常式的相關概念、結構特點和樣本。
如您需要通過HTTP觸發器或自訂網域名訪問函數,請先擷取請求結構體再自訂HTTP響應。更多資訊,請參見HTTP觸發器調用函數。
什麼是請求處理常式
FC函數的請求處理常式,是函數代碼中處理請求的方法。當您的FC函數被調用時,Function Compute會運行您提供的Handler方法處理請求。
您可以通過Function Compute控制台,在建立或更新函數時為函數配置請求處理常式。具體操作,請參見建立事件函數。
對於C#語言的FC函數,其請求處理常式的格式為程式集名稱::命名空間.類名::方法名
(Assembly::Namespace.ClassName::MethodName
)。
參數 | 說明 |
Assembly | 建立的程式集的名稱。 |
Namespace | 命名空間名稱。 |
ClassName | 類名。 |
MethodName | 方法名。 |
假設程式集名稱為HelloFcApp
,則請求處理常式的配置為HelloFcApp::Example.HelloFC::StreamHandler
。一個簡單的程式樣本如下。
using System.IO;
namespace Example
{
public class HelloFC
{
public async Task<Stream> StreamHandler(Stream input)
{
//function logic
}
}
}
請求處理常式的具體配置均需符合Function Compute平台的配置規範。配置規範因請求處理常式類型而異。
處理常式介面
當您建立一個基於C#的函數時,需要指定一個Handler方法,該方法在函數執行時被執行。這個Handler方法可以是Static方法或Instance方法。如果您想在Handler方法中訪問IFcContext
對象,則需要將該方法中的第二個參數指定為IFcContext
對象。事件函數支援的Handler方法定義如下所示。
ReturnType HandlerName(InputType input, IFcContext context); //包含IFcContext。
ReturnType HandlerName(InputType input); // 不包含IFcContext。
Async Task<ReturnType> HandlerName(InputType input, IFcContext context);
Async Task<ReturnType> HandlerName(InputType input);
Function Compute支援在使用C#編寫的函數中應用Async,此時函數的執行會等待非同步方法呼叫執行結束。以下是對ReturnType、InputType和IFcContext的說明。
ReturnType:返回對象可以是
void
、System.IO.Stream
對象或者任何可以被JSON序列化和還原序列化的對象。如果返回對象是Stream,該Stream內容將直接在響應體返回,否則返回對象被JSON序列化後,在響應體返回。InputType:輸入參數可以是System.IO.Stream或任何可以被JSON序列化和還原序列化的對象。
IFcContext:函數的Context對象。更多資訊,請參見上下文。
事件請求處理常式類型
Function Compute使用C#編寫函數,需要引入Aliyun.Serverless.Core
依賴包,可以通過以下方式,在.csproj檔案中引入該依賴包。
<ItemGroup>
<PackageReference Include="Aliyun.Serverless.Core" Version="1.0.1" />
</ItemGroup>
Aliyun.Serverless.Core
包為事件請求處理常式定義了兩個參數類型。
Stream Handler
以流的方式接收輸入的
event
事件並返回執行結果,您需要從輸入資料流中讀取調用函數時的輸入,處理完成後把函數執行結果寫入到輸出資料流中來返回。POCO Handler
通過POCO(Plain old CLR objects)方式,您可以自訂輸入和輸出的類型,但是輸入和輸出的類型必須是POCO類型。
Stream Handler
一個最簡單的Stream Handler樣本如下所示。
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){}
}
}
樣本解析如下。
命名空間和類
命名空間為
Example
,類名為Hello
,方法名為StreamHandler
,假設程式集名稱為HelloFcApp
,則請求處理常式的配置為HelloFcApp::Example.Hello::StreamHandler
。參數Stream input
處理常式的輸入,該樣本的輸入類型為Stream。
參數IFcContext context(可選)
內容物件,包含函數和請求的資訊。
傳回值Task<Stream>
傳回值為Stream類型。
POCO Handler
一個最簡單的POCO Handler樣本如下所示。
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 serializer class, if it’s not specified, the default serializer (based on JSON.Net) will be 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){}
}
}
除了Stream作為輸入輸出參數,POCO(Plain old CLR objects)對象同樣也可以作為輸入和輸出。如果該POCO沒有指定特定的JSON序列化對象,則Function Compute預設使用JSON.Net進行對象的JSON序列化和還原序列化。具體解析如下。
命名空間和類
命名空間為
Example
,類名為Hello
,方法名為PocoHandler
,假設程式集名稱為HelloFcApp
, 則請求處理常式的配置為HelloFcApp::Example.Hello::PocoHandler
。參數
Product product
處理常式的輸入,該樣本的輸入類型為
Product Class
。如果該POCO沒有指定特定的JSON序列化對象,則Function Compute預設使用JSON.Net進行對象的JSON還原序列化。參數IFcContext context(可選)
內容物件,包含函數和請求的資訊。
傳回值
Product
傳回值為
POCO Product
類型。如果該POCO沒有指定特定的JSON序列化對象,則Function Compute預設使用JSON.Net進行對象的JSON序列化。
自訂序列化介面(Custom Serializer)
Function Compute針對POCO Handler提供了預設的基於JSON .NET的序列化介面。如果預設的序列化介面不能滿足需求,您可以基於Aliyun.Serverless.Core
中的介面IFcSerializer
實現自訂序列化介面。
public interface IFcSerializer
{
T Deserialize<T>(Stream requestStream);
void Serialize<T>(T response, Stream responseStream);
}
使用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觸發器並使用HTTP觸發。
操作步驟
登入Function Compute控制台,在左側導覽列,單擊函數。
在頂部功能表列,選擇地區,然後在函數頁面,單擊目標函數。
在函數詳情頁面,單擊觸發器管理頁簽,擷取HTTP觸發器的公網訪問地址。
在Curl工具執行以下命令,調用函數。
curl -i "https://test-python-ipgrwr****.cn-shanghai.fcapp.run" -d 'Hello fc3.0'
以上命令中,
https://test-python-ipgrwr****.cn-shanghai.fcapp.run
為擷取到的HTTP觸發器公網訪問地址。響應結果如下。
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
錯誤分析
本範例程式碼支援使用HTTP觸發器或者自訂網域名調用。如果使用API調用,但配置的測試參數不符合HTTP觸發器請求格式規範時,會出現報錯。
例如,在控制台上調用函數,配置請求參數為"Hello, FC!"
,單擊測試函數,收到的響應如下所示。
{
"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"
]
}
樣本程式
Function Compute官方庫包含使用各種處理常式類型和介面的應用程式範例。每個應用程式範例都包含用於輕鬆編譯部署的方法。
dotnet3-blank-stream-event:使用Stream格式的事件回調處理常式。
dotnet3-blank-poco-event:使用POCO格式的事件回調處理常式。