はじめに
最近知ったのですが,AWS LambdaがC#に対応しているらしいです。C#大好きっ子としては触らなきゃということで簡単なWebAPIを作ってみました。
AWS Lambda はサーバーレスコンピューティングサービスで、サーバーのプロビジョニングや管理、ワークロード対応のクラスタースケーリングロジックの作成、イベント統合の維持、ランタイムの管理を行わずにコードを実行できます。Lambda を使用すれば、実質どのようなタイプのアプリケーションやバックエンドサービスでも管理を必要とせずに実行できます。
AWS Lambda(イベント発生時にコードを実行)| AWS
一応AWS Lambdaの冒頭の説明文を載せときます。
では早速やっていきましょう。
AWS Toolkit for Visual Studioをインストールする
お手元のVisual StudioにAWS Toolkit for Visual Studioをインストールすれば、コーディング&デプロイまでをVisual Studioで行うことができます。
AWS Toolkit for Visual Studio は、Microsoft Windows で実行される Microsoft Visual Studio の拡張機能です。開発者は、アマゾン ウェブ サービスを使用する .NET アプリケーションの開発、デバッグ、デプロイが容易にできるようになります。AWS Toolkit for Visual Studio を使用すると、AWS アプリケーションの構築をより迅速に開始でき、生産性が向上します。
まずはVisual Studioを起動してください。(私の場合はVisual Studio 2019)
とりあえずコードなしで続行を押し、上のツールバーから、拡張機能 -> 拡張機能の管理を選択します。



あとは再起動すればOKです。
補足
AWS Toolkit for Visual StudioはどうやらVisual Studio for Macでは動作しないようです。(2021/05/18時)
ですので、Visual Studio Code用のAWS Toolkit for Visual Studio Codeを代わりに使うことが多いようです。

プロジェクトを作成する
Visual Studioを立ち上げ、新しいプロジェクトを作成を選択すると、AWS Lambda Project (.NET Core - C#)が追加されているはずですので選択します。

どのテンプレート利用してを作成するか聞かれる(Select Blueprint)ので、今回は最小構成であるEmpty Functionを選択しました。

無事にプロジェクトが作成されると、以下の構成でファイルが生成されます。

.Project |---- Properties | └ launchSettings.json |--- Function.cs |--- aws-lambda-tools-defaults.json --- readme.md
※ 厳密には他のファイルも生成されいますが、VisualStudioのソリューションエクスプローラーで確認できるものを掲載
自身のAWSのアカウントのアクセスキーを確認する
自分のAWSアカウントにログインを行い、マイセキュリティ資格情報という欄からアクセスキーとシークレットアクセスキーを取得します。

私の場合はまだ作成していなかったので、新しいアクセスキーを作成を押し、作成された2つの文字列をメモしておいてください。
VisualStudioとAWSのアカウントを紐づける
取得したアクセスキーを用いて、Visual Studioを自身のAWSと紐づけます。
VisualStudioにて表示 -> AWS Explorerを選択し、AWS Explorerを開いてください。

無事に開けると以下の画像のような表示になると思うので、人の右上にプラスマークが書かれているボタンを押してユーザーの追加を行います。

先程取得しアクセスキーとシークレットアクセスキーを利用して、項目を埋めOKを押せばユーザーの追加は完了です。
ちなみにProfile Nameはお好きな名前で、Regionは東京がいいでしょう。

無事に自身のAWSアカウントに接続できればAWS Explorerに色々な情報が追加されているはずです。

コードを記述してみる
生成されたファイルで一番重要なのがFunction.csです。ここに実行したいコードを記述していきます。
デフォルトでは以下のコードが生成されているはずです。
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Amazon.Lambda.Core; // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace AWSLambdaTest { public class Function { /// <summary> /// A simple function that takes a string and does a ToUpper /// </summary> /// <param name="input"></param> /// <param name="context"></param> /// <returns></returns> public string FunctionHandler(string input, ILambdaContext context) { return input?.ToUpper(); } } }
初めてのコーディングはやっぱりHello, Worldだろうということで、とりあえずHello, Worldを返す関数を作成しました。
using Amazon.Lambda.Core; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Net; using System.Text.Json; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] namespace AWSLambdaTest { public class Function { public LambdaResponse FunctionHandler(object input, ILambdaContext context) { var body = new Dictionary<string, string>() { { "message", "Hello, World" }, }; var response = new LambdaResponse() { isBase64Encoded = false, statusCode = HttpStatusCode.OK, headers = new Dictionary<string, string>() { {"my_header", "my_value" } }, body = JsonConvert.SerializeObject(body), }; return response; } public class LambdaResponse { [JsonProperty(PropertyName = "isBase64Encoded")] public bool isBase64Encoded; [JsonProperty(PropertyName = "statusCode")] public HttpStatusCode statusCode; [JsonProperty(PropertyName = "headers")] public Dictionary<string, string> headers; [JsonProperty(PropertyName = "body")] public string body; } } }
コードの書き方については以下の公式サイトを参照するのが確実です。
docs.aws.amazon.com
また今回書いたコードはNewtonsoft.JsonとAmazon.Lambda.Serialization.Jsonというライブラリへの依存があるので、ツール -> NuGetパッケージマネージャー -> ソリューションのNuGetパッケージ管理により2つをインストールしてください。

また単純にAWS Lambdaのコードを作るだけならもっと簡単にできるのですが、AWS Gatewayを使ってWebAPI化するには返り値の細かい仕様があります。(最初これに気付かずかなり苦戦しました。。。)
API ゲートウェイでの「不正な Lambda プロキシ応答」または 502 エラーの解決
{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "body": "..." }
コードをデプロイする
記述したコードをAWSにデプロイしてみましょう。
右側に表示されているソリューションエクスプローラーからプロジェクトを選択・右クリックし、Publish to AWS Lambda ...をクリック。

すると色々と情報を聞かれるので、それぞれ入力を行ってください。

一番上にあるRole Nameが曲者で、Lambda 機能を使用するために必要なアクセス許可を設定するみたいです。
AWS Lambda 実行ロール - AWS Lambda
正直なところどれを選べばいいかよく分からなかったのですが、とりあえずデフォルトっぽいAWS Lambda Roleを選択しました。
あとはメモリ・タイムアウトをそれぞれ128, 10sに設定してみて、Uplodeを実行。

デプロイした関数のテストを行う
アップロードが完了すると、Visual StudioでAWS上にある関数のテストが行えるようになります。

今回作成したメソッドの引数はなくても動くので、実行ボタンを押せばHello, Worldが表示されているはずです。
AWS上で関数のテストをする
一応AWS Console上での関数のテストのやり方を紹介しておきます。
AWS Lambdaの管理画面を開くと、先程作成した関数が表示されているはずです。(リージョンを間違えないように)

関数名をクリックした後、テストというタグを押します。

後はVisualStudioで行ったようにテストを実行します。


WebAPI化する
結構長期戦になってきましたが、あとWeb API化すれば完成です。もう少し頑張りましょう。
APIを作成するにはAmazon API Gatewayを利用します。
ただAWS Lambdaの関数の画面から簡単に設定できるので身構える必要はありません。
テストをしていた画面の上にスクロールするとトリガーの追加というボタンがあるはずです。

クリックすると以下の画面がでるはずなので、API Gatewayを選択します。

すると詳細の入力画面が出てくるので、以下の画像を参考にしながら追加してください。

テストしてみる
おそらくこれまでの操作がうまくいっていればそのままAPI エンドポイントのリンクを踏めば動くはずですが、一応テストをしておきましょう。
自分でAWS Gatewayの管理画面を開いてください。一応以下の画像の赤く囲われたところを押せば管理画面に遷移することができます。

すると以下のような画面になるはずですので、テストをクリック。

今までの手順で作成したらRest APIの全てのメソッドに対して処理を走らせる(設定から変えられます)ようになっているのですが、今回書いたコードはGETメソッドでも正しく動作するのでGETで確かめてみます。

実験してみる
最後に、実際にURLをたたいて確かめてみましょう。URLはAWS Lambdaのトリガーの詳細のところに書いてあります。

実行してみると....。

さいごに
10000文字ぐらいある想像以上に長い記事になってしまって、書いている私自身へとへとになってきてしまいました。無事にここまでできた方はお疲れ様です。
途中でも少し書いたのですが、コードの返り値に仕様があったのを完全に見落としていて502エラーが永遠に出てきて大変でした。
ただ一度やり方を覚えてしまえばBodyの中身を書き換えるだけなので、なんでもできちゃいます。無敵です。
良かったらうまく活用してみてください。
ではまた。