aws / aws-lambda-dotnet

Libraries, samples and tools to help .NET Core developers develop AWS Lambda functions.
Apache License 2.0
1.57k stars 479 forks source link

Combination of ASP.NET (Minimal API) and [LambdaFunction] annotations in the same csproj #1782

Closed michael-freidgeim-webjet closed 2 months ago

michael-freidgeim-webjet commented 3 months ago

Describe the feature

We have a lambda created as ASP.NET minimal API that calls services.AddAWSLambdaHosting(LambdaEventSource.ApplicationLoadBalancer); and has existing external clients that are using ApplicationLoadBalancer. The current limitation is that such project expects only ApplicationLoadBalancer request format. We want to have multiple lambda functions in the same csproj to support calls from different event sources. This functionality is supported by annotations, (see https://chatgpt.com/share/b51a30a1-0f69-459c-ba2b-5448165e86b5 ), but not in AWS ASP.NET lambda Program.cs project, that required to specify only one of 3 options in services.AddAWSLambdaHosting(LambdaEventSource) call. Do we have to rewrite ASP.NET minimal API project to LambdaFunction annotations due to this restriction? Or it's possible to have both Asp.Net Program.cs file with services.AddAWSLambdaHosting and Functions.cs with [LambdaFunction] in the same .csproj file? If it's not possible, please consider to support multiple LambdaEventSource in the same ASP.Net csproj

Use Case

Ability to add lambdas called from amazon connect to the existing project written as ASP.Net Minimal API with calls from ApplicationLoadBalancer

Proposed Solution

have both Asp.Net Program.cs file with services.AddAWSLambdaHosting and Functions.cs with [LambdaFunction] in the same .csproj file?

Other Information

No response

Acknowledgements

AWS .NET SDK and/or Package version used

3.7.302.15

Targeted .NET Platform

.Net 8

Operating System and version

deployed lambdas to AWS, on Dev Windows 11

normj commented 2 months ago

If I understand what you are asking I got a solution by setting a LambdaEventSource environment variable for the Lambda function that specifies the Lambda event source for that function. This CloudFormation template specifies 2 different Lambda functions one using an API Gateway Rest API and the other using API Gateway Http Api. Same idea would work for Application load balancer but it was easier for me to quickly test with API Gateway. Both CloudFormation function resource is pointing to same project but uses a different resource path in the event source.

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
  "Parameters": {},
  "Conditions": {},
  "Resources": {
    "RootFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "AspNetCoreLambdaDifferentEventSources",
        "Runtime": "dotnet8",
        "CodeUri": "",
        "MemorySize": 512,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          "AWSLambda_FullAccess"
        ],
        "Environment" : {
            "Variables" : {
                "LambdaEventSource" : "RestApi"
            }
        },
        "Events": {
          "RootResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/",
              "Method": "ANY"
            }
          }
        }
      }
    },
    "CalculatorFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "AspNetCoreLambdaDifferentEventSources",
        "Runtime": "dotnet8",
        "CodeUri": "",
        "MemorySize": 512,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          "AWSLambda_FullAccess"
        ],
        "Environment" : {
            "Variables" : {
                "LambdaEventSource" : "HttpApi"
            }
        },
        "Events": {
          "ProxyResource": {
            "Type": "HttpApi",
            "Properties": {
              "Path": "/calculator/{proxy+}",
              "Method": "ANY"
            }
          }
        }
      }
    }
  },
  "Outputs": {
    "RootURL": {
      "Description": "API endpoint URL for Prod environment",
      "Value": {
        "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
      }
    },
    "CalculatorURL": {
      "Description": "API endpoint URL for Prod environment",
      "Value": {
        "Fn::Sub": "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/calculator/"
      }
    }
  }
}

Then in the code that calls AddAWSLambdaHosting check the environment variable to figure out what event source to pass into the call.

var eventSource = Environment.GetEnvironmentVariable("LambdaEventSource");
switch(eventSource)
{
    case "RestApi":
        builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);
        break;
    case "HttpApi":
        builder.Services.AddAWSLambdaHosting(LambdaEventSource.HttpApi);
        break;
}
normj commented 2 months ago

I'm going to close this assuming my response gave you enough info move forward. Feel free to reopen or create a new issue if this didn't answer your question.

github-actions[bot] commented 2 months ago

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

michael-freidgeim-webjet commented 2 months ago

@normj thank you for your suggestion. We also found that it’s possible in the same Csproj to contain both asp.net minimal api Program.cs and Annotations Functions.cs. They are declared as separate lambdas in serverless.template (with comment “This template is partially managed by Amazon.Lambda.Annotations”).

It will be good to mention one or both of these solutions in the ASP.NET documentation, because even AWS support engineers advised us, that it’s not possible to mix LambdaEventSources in ASP.NET minimal API csproj.