c#＋Lambda＋API Gatewayで最小構成のRestAPIを作成する方法

直近ではPythonを使ってLambda+serverless framework+APIGatewayでRestAPIを作成していたのですが、そちらのプロジェクトが終わって知見を広めようとバックエンド系の言語を調べていた所、C#の文字を発見！
これまでC#はwindows用のアプリを開発する言語として利用してきたので、バックエンドでも使えることを知ってびっくりしました。

まだまだ初歩も初歩の部分をやっているのですが、初歩の部分のハードルがかなり高くて、自分でも2回目やるときにまた調べなきゃいけないことになりそうだったので、最小のAPIを作成してデプロイするところまでを手順化してみます！

# 環境
windows11
VisualStudio2022Community 17.8.6
.NET6



# まずVisualStudioを変更する
1. VisualStudioInstallerを起動して、変更を選択します。
2. **ASP.NETとWEB開発**にチェックを入れて右下の変更を押します。
3. しばらく待つとVisualStudioが変更されるので、これで完了です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/b851f158-3d0c-9f5a-d632-03ab4d311747.png)

# プロジェクトの作成
1. 新しいプロジェクトの作成 をクリック
2. テンプレートから**ASP.NET Core Web API**を選択
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/b73763b9-08b3-bcb6-6150-871c422018d7.png)
 3. 任意のプロジェクト名とソリューション名を設定し、場所の指定をし、次へを押す
 3. 追加情報の設定は基本的にはデフォルトで問題ないかなと思います。
     フレームワークは``.NET6.0``、認証の種類は``なし``、HTTPS用の構成とOpenAPIサポート...とコントローラーを使用するにチェック☑を入れる。
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/1c31608d-85b3-e6d4-1c4f-dad2c390fbad.png)

これでプロジェクトの作成が完了しましたね！

::: note info
この時点でローカルホストではAPIが動作するようになっているので、``F5`` or ``Ctrl+F5``で実行するとSwaggerViewがブラウザで立ち上がってローカルホストでAPIを叩けるようになります。
:::

# NuGetパッケージのインストール
1. まずはLambdaにデプロイするために必要なNuGetパッケージをインストールします。
1. **プロジェクト**タブからNuGetパッケージの管理を選択し、参照タブで検索窓に``amazon.lambda.asp``と入力する。
3. そうすると、``Amazon.Lambda.AspNetCoreServer.Hosting``というパッケージが出てくるので、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/4f9ee825-e9b9-93eb-f034-580b60bbfd89.png)
4. ポップアップが表示されたら``同意する``を押して、インストールの完了です。

# プロジェクトファイルの編集
1. まずは``.csproj``ファイルを編集します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/e73f798e-aab8-9a99-b08a-80a5eba2d303.png)
1. ``PropertyGroup``セクションに``<AWSProjectType>Lambda</AWSProjectType>``という文言を追加します。 

```xml:testAPI.csproj
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <AWSProjectType>Lambda</AWSProjectType>
  </PropertyGroup>
```

3\. これで、このプロジェクトがLambda関数を開発しているとVisualStudioに認識させることができます。

::: note info
``<AWSProjectType>Lambda</AWSProjectType>``を追加する前と後では、``.csproj``ファイルを右クリックしたときに表示されるメニューが違います。
デフォルトでは``Publish to AWS...``とAWSのすべてのサービスに対してデプロイするメニュー(使ったことがないので詳しくは知りません)ですが、``AWSProjectType``プロパティに``Lambda``を設定すると、``Publish to AWS Lambda...``というようにLambdaにデプロイする用のメニューに進化します。
:::

# Lambda関数にHTTPリクエストを送信するイベントを設定する
1. 難しいことが書いてありますが、要はLambdaをトリガーする際のイベントを設定するというだけの事です。
今回はRestAPIでLambdaの発火を行うので、そのように設定します。
1. ``Program.cs``を開き、``var app = builder.Build();``の上の行に``builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);``を追加します。

```c#:Program.cs
builder.Services.AddSwaggerGen();

builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);   //ここに追加

var app = builder.Build();
```

これだけでOKです！

:::note info
``RestApi``の部分を``HttpApi``にすることでHTTP APIでも発火できます。
:::

# Lambda関数を作成する
1. AWSコンソールからLambdaを開きます。
1. **関数を作成**ボタンをクリックして、関数の作成画面に移行します。
1. 関数名に任意の名前を入力し、ランタイムに``.NET 6(C#/PowerShell)``を選択して**関数を作成**ボタンを押す。
1. AWSコンソールでの操作は以上です。

# Lambdaにデプロイする
1. ここまで出来たら、ついにLambdaにローカルの関数をデプロイしていきます。
1. まずはアセンブリ名を確認します。
    1. **.csproj**を右クリックし、プロパティを開きます。
    1. アプリケーションタブのアセンブリ名を確認して必要であればメモしておきます。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/52869a10-0445-8d07-5a61-d88a2c035803.png)
1. **.csproj**を右クリックし、``Publish to AWS Lambda...``をクリック。
1. すると、Lambdaデプロイする用のインターフェースが表示されます。
1. **FunctionName**で``Re-deploy to existing``にチェックを入れて、先ほどAWSコンソールで作成したLmabda関数を選択して、**Handler**にアセンブリ名を入力して**Next**を押します。  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/648be3a6-3bae-f2ea-f96b-e59d48d38acf.png)


1. デプロイの設定画面が表示されるので、**RoleName**には、先ほど作成したLambda関数の名前がついているものを選択してください。(例 : ``test_lambda_role_xxxxxxxxx``)
1. 他の設定もできますが、今回はそれ以外は特に触れずに、**Upload**ボタンを押します。
1. 何事もなければ、publishingと表示され、アップロード作業が完了すると自動的にクローズします。
1. その後表示される画面でテストができるのですが、今回の構成ではテストしてもエラーが出るので、パスします。
1. これで、Lambda関数側は完了になります！

# API GatewayでAPIを作る
1. これまで色々やってきたLambda関数を発火する用のAPIを作成します。
2. AWSコンソールにアクセスし、APIGatewayのコンソールを開きます。
3. 作成出来るAPIの種類が表示されるので、REST APIの**構築**をクリックする。(APIの種類が表示されず、既存のAPI一覧が表示される場合は、APIを作成ボタンをクリックすると表示されます)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/090f099b-82c9-bf08-91cc-efccb681f533.png)
4. API名だけ任意のものを付けて、他はデフォルトのままAPIを作成をクリック。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/29fb0069-0325-dd80-dce0-9eaa36c80e85.png)
5. リソースを作成をクリック。
6. **プロキシのリソース**をONにして。リソース名に``{proxy+}``と入力してリソースの作成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/925d1521-41c9-5c8a-7b16-16feb8b81049.png)
7. 右側のリソースツリーから``/{proxy+}``を選択して、**メソッドを作成**ボタンをクリック。
8. メソッドタイプは、今回のLambda関数は天気を取得するものなので、GETを選択します。
9. **Lambda関数**には、先ほど作成したLambda関数を選択し、メソッドを作成をクリックします。
10. 続いて、リソースツリーから、**ANY**を選択し、**統合を編集**ボタンをクリックします。
10. **Lambda関数**で先ほど作成したLambda関数を選択し、他は何も触れずに**保存**を押します。
10. ここまで出来たら、右上にある**APIをデプロイ**をクリックし、``ステージを選択``プルダウンをクリックし、``新しいステージ``で、**ステージ名**には任意の名前を付けて**デプロイ**ボタンをクリックします。
10. これで、APIを作成す、Lambdaと紐づけることができたので、あとは動作チェックだけです。

# 実際に動作チェックする
1. あとは簡単で、実際にAPIGatewayで作成されたURLにアクセスして、APIが動いているか確認するだけです。
1. まず、APIGatewayのコンソールを表示して、作成したAPIをクリックします。(先ほどAPIを作成した画面のままならパスで大丈夫です)
1. 左側のサイドバーから**ステージ**の項目をクリックします。
1. すると、``ステージの詳細``という画面が表示されるので、そこの中央あたりにある**URLを呼び出す**というセクションに書いてあるURLをコピーします。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588962/e2fabd7c-424d-b154-e434-8a91184743d6.png)
1. 新しくタブを開いて、先のURLを張り付けます。
1. これだけでは``{"message":"Missing Authentication Token"}``が表示されてしまうはずなので、エンドポイントを編集します。
1. いったんVisualStudioに戻って、``Controllers\WeatherForecastController.cs``を開きます。
1. ここに書いてあるのが実際のLambda関数なのですが、クラス名がエンドポイントになっています。 
 ```C#:WeatherForecastController.cs
namespace testAPI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    // Routeアトリビュートでの指定によるが、controllerを指定した場合、
    // クラス名からControllerを引いたものがエンドポイントになる
    public class WeatherForecastController : ControllerBase
```
9\. この場合は、``WeatherForecast``がエンドポイントとなるので、``{先ほどコピーしたURL}/WeatherForecast``をブラウザで叩きます。
10. すると、 
```json:result
 [{"date":"2024-02-27T09:13:18.9855303+00:00","temperatureC":22,"temperatureF":71,"summary":"Mild"},{"date":"2024-02-28T09:13:19.0011868+00:00","temperatureC":14,"temperatureF":57,"summary":"Hot"},{"date":"2024-02-29T09:13:19.0011904+00:00","temperatureC":3,"temperatureF":37,"summary":"Freezing"},{"date":"2024-03-01T09:13:19.0011907+00:00","temperatureC":4,"temperatureF":39,"summary":"Mild"},{"date":"2024-03-02T09:13:19.0011908+00:00","temperatureC":26,"temperatureF":78,"summary":"Warm"}]
```
11\.このようにブラウザに表示されれば無事APIとして動作していることになります！

# 振り返り
C#でAPIを作れるには作れるのですが、Pythonほど日本語の資料や記事も無く、AWSの公式リファレンスでもあまり取り上げられていないので、なかなか難しかったです。
幸い、海外の方が動画でチュートリアルを挙げてくださっていて、その通りにしたらしっかりAPIが作れたので、今回はそのまま翻訳したような形にはなりましたが、記事にしてみました。
気が向いたら、C#で実際に実用的なAPIを作成したり、そもそものASP.NET Cre WEB APIでデフォルト作成されるフォルダの解説なんかも書いてみようと思います。






---
参考にした動画 : [Building a Serverless ASP.NET Core Web API using AWS Lambda and Amazon API Gateway REST API](https://www.youtube.com/watch?v=58kZOQw-Bvk)