1
votes

I have a controller behind an AspNetCoreServer.APIGatewayProxyFunction (AWS lambda function to route to WebApi) with this action method in my controller:

[HttpGet("{id}")]
public async Task<MyClass> Get(ulong tagId)
{
    Amazon.Lambda.Core.LambdaLogger.Log($"Get(tagId) is called with {tagId}");
    return new MyClass { Id = tagId, Description = "Something" };
}

It routes correctly to this method but it does not pass the value specified as Id in the url. In fact, the problem is "id" is always 0. I changed the method signature to be "string id" but the method always received empty string then.

Hitting the APIGateway endpoint (Prod is the stage):

https://*********.execute-api.*****.amazonaws.com/Prod/api/MyController/1000

Output in the browser:

{
    Id: 0,
    Description: "Something",
}

Cloudwatch:

Get(TagId) is called with 0

I have deployed with AWS toolkit from within Visual Studio (tried dotnet lambda CLI as well with no difference). I have deployed API within API Gateway console. There is another action method that returns all values (no passed argument to the method) and that one is fine, only this action method with an input fails to read the value.

Inside my Startup.cs:

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public static IConfiguration Configuration { get; private set; }

        // This method gets called by the runtime. Use this method to add services to the container
    public void ConfigureServices(IServiceCollection services)
    {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);    
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc();
    }

Running this code locally with "AWS .NET Mock Lambda Test Tool" results the same, Id will be 0.

Can someone help me here please? I am running out of ideas.

1
Why would cloud watch have TagId?Nkosi
Good catch. I had renamed variables before pasting in here. I edited the question now to reflect the exact naming. The real argument name is tagId and that explains the log in CloudWatch.Rez.Net
What about in the route template? {id} was that the original problem?Nkosi
yes it was. so I had the option of having either {tagId} matching the action method signature, or renaming the argument in the action method to match {id}Rez.Net

1 Answers

0
votes

Change tagId from ulong to long and you can also use it as a route constraint.

Ensure that the parameter name and route template parameter name matches.

There is no await code in the action so there is no need for async Task

[Route("api/MyController")]
public class MyController {
    //GET api/MyController/1000
    [HttpGet("{tagId:long}")]
    public MyClass Get(long tagId) {
        Amazon.Lambda.Core.LambdaLogger.Log($"Get(tagId) is called with {tagId}");
        return new MyClass { Id = tagId, Description = "Something" };
    }
}

Most likely the model binder is unable to bind the ulong parameter

Routing in ASP.NET Core: Route constraint reference