MattG
MattG

Reputation: 6445

Why is AWS Lambda failing to reach the FunctionHandler?

I am:

  1. deploying a C# app to Lambda to the first time.
  2. using Mac so can't use the Visual Studio AWS Toolkit Extension.
  3. using C# .NET core 3.1.
  4. deploying using: dotnet lambda deploy-serverless

The deployment seems to work without errors, the Lambda is visible in the AWS Console.

When I test the Lambda from AWS Console log output is generated, some of which is from my C# code. Such as this line "LambdaEntryPoint - init".

However none of the log output in my handler (FunctionHandlerZ) is written to the log.

I see this exception when I use the AWS Console Test facility:

{
  "errorType": "NullReferenceException",
  "errorMessage": "Object reference not set to an instance of an object.",
  "stackTrace": [
    "at Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction.MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)",
    "at Amazon.Lambda.AspNetCoreServer.AbstractAspNetCoreFunction`2.FunctionHandlerAsync(TREQUEST request, ILambdaContext lambdaContext)",
    "at Amazon.Lambda.RuntimeSupport.HandlerWrapper.<>c__DisplayClass25_0`2.<<GetHandlerWrapper>b__0>d.MoveNext()",
    "--- End of stack trace from previous location where exception was thrown ---",
    "at Amazon.Lambda.RuntimeSupport.LambdaBootstrap.InvokeOnceAsync(CancellationToken cancellationToken)"
  ]
}

LambdaEntryPoint.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using System.IO;
using Amazon.Lambda.Core;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace aspDemo3B
{
    public class LambdaEntryPoint :
        // When using an ELB's Application Load Balancer as the event source change 
        // the base class to Amazon.Lambda.AspNetCoreServer.ApplicationLoadBalancerFunction
        Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
    {
        /// <summary>
        /// The builder has configuration, logging and Amazon API Gateway already configured. The startup class
        /// needs to be configured in this method using the UseStartup<>() method.
        /// </summary>
        /// <param name="builder"></param>
        protected override void Init(IWebHostBuilder builder)
        {
            Console.WriteLine("LambdaEntryPoint - init");

            builder
                .UseStartup<Startup>();
        }

        public string FunctionHandlerZ(string input, ILambdaContext context)
        {
            Console.WriteLine("FunctionHandlerZ");
            Console.WriteLine($"Calling function name: {context.FunctionName}\\n");
            return input?.ToUpper();
        }
    }
}

serverless.template

{
  "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": {
    "AspNetCoreFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "aspDemo3B::aspDemo3B.LambdaEntryPoint:FunctionHandlerZ",
        "Runtime": "dotnetcore3.1",
        "CodeUri": "",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          "AWSLambdaFullAccess"
        ],
        "Environment": {
          "Variables": {
            "LAMBDA_NET_SERIALIZER_DEBUG": "true"
          }
        },
        "Events": {
          "ProxyResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/{proxy+}",
              "Method": "ANY"
            }
          },
          "RootResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/",
              "Method": "ANY"
            }
          }
        }
      }
    }
  },
  "Outputs": {
    "ApiURL": {
      "Description": "API endpoint URL for Prod environment",
      "Value": {
        "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
      }
    }
  }
}

I am happy to start from scratch with a simple helloWorld style Lambda that:

  1. Does not require AWS Toolkit Extension, as it is not available on Mac.
  2. Uses .NET core 3.1 (there have been some changes from 3.0 to 3.1 for AWS Lambda)
  3. Is initiated by a HTTP request via API GW and returns a simple response

Upvotes: 4

Views: 5519

Answers (1)

Bharath Kumar Reddy
Bharath Kumar Reddy

Reputation: 46

Below is will help you

public class LambdaFunctionHandler : APIGatewayProxyFunction
{

    protected override void Init(IWebHostBuilder builder)
    {
        builder.UseStartup<Startup>();
        // DemoWebApi::DemoWebApi.ALBLambdaFunction::FunctionHandlerAsync
    }
}

not required FunctionHandlerZ function

For any Lambda API you are using API Gateway FunctionHandlerAsync will be the entry point.

Lambda Function Handler should be as [AssemblyName]::[NameSpace].[Classname]::FunctionHandlerAsync

Upvotes: 1

Related Questions