Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BadImageFormatException when using serverless.AspNetCoreWebApp template with Mock Lambda Test Tool #1075

Closed
1 task
coultonluke opened this issue Feb 7, 2022 · 19 comments
Assignees
Labels
bug This issue is a bug. module/lambda-test-tool p2 This is a standard priority issue queued response-requested Waiting on additional info and feedback. Will move to close soon in 7 days.

Comments

@coultonluke
Copy link
Contributor

coultonluke commented Feb 7, 2022

Description

Can't make request to lambda using Mock Lambda Test Tool when project has reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation Nuget package.

Reproduction Steps

  1. Install templates: dotnet new -i "Amazon.Lambda.Templates::*"

  2. Create new project: dotnet new serverless.AspNetCoreWebApp

  3. Add Nuget reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

  4. Edit ConfigureServices in startup to enable razor pages to be loaded:

     public void ConfigureServices(IServiceCollection services)
     {
         services.AddControllers();
         var builder = services.AddRazorPages();
         builder.AddRazorRuntimeCompilation();
     }
    
  5. Configure debug configuration for mock test tool as shown in the readme for Rider:
    Executable and executable path: "\.dotnet\tools\.store\amazon.lambda.testtool-3.1\0.11.4\amazon.lambda.testtool-3.1\0.11.4\tools\netcoreapp3.1\any\Amazon.Lambda.TestTool.BlazorTester.dll"

  6. Create a controller and use attribute routing

  7. Debug application and send in request using Mock Test Tool blazor interface

Request I'm using: { "httpMethod": "GET", "path": "/api/Home" }

Without Nuget reference:
image

With Nuget reference:
image

Logs

Environment

  • Build Version: Amazon.Lambda.AspNetCoreServer 7.0.1
  • OS Info: Windows 10
  • Build Environment: Jetbrains Rider
  • Targeted .NET Platform: netcoreapp3.1

Resolution

  • Remove reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (no use for local debugging)

A similar issue also happens when I reference Microsoft.AspNetCore.Mvc.WebApiCompatShim too, but the error is that it can't find System.Json.


This is a 🐛 bug-report

@coultonluke coultonluke added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Feb 7, 2022
@ashishdhingra
Copy link
Contributor

Hi @coultonluke,

Good morning.

I was able to reproduce the issue in Visual Studio (not Jetbrains Rider) by:

  • Creating serverless.AspNetCoreWebApp project
  • Adding reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation version 3.1.22 (since this is the latest version compatible with NetCoreApp31)
  • Enabling controller endpoints (endpoints.MapControllers();)
  • Adding a minimal HomeController:
[Route("api/[controller]")]
public class HomeController : Controller
{
    [HttpGet]
    public string Index()
    {
        return "Hello";
    }
}
  • Debug using Mock Lambda Test Tool.

I manually tried adding reference to Microsoft.CSharp 4.0.0 NuGet package, however, it gave the warning NU1701 | Package 'Microsoft.CSharp 4.0.0' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETCoreApp,Version=v3.1'. This package may not be fully compatible with your project..

Kindly note that Mock Lambda Test Tool uses reflection to load all the dependent assemblies. I'm unsure if Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation tries to load Microsoft.CSharp 4.0.0 at runtime in a different context.

Thanks,
Ashish

@coultonluke
Copy link
Contributor Author

Thank you for looking into this for me. I appreciate it. I'm trying to get going with the Lambda Test Tool using an existing project, so do you think I'll just have to remove that reference and it's functionality in order to use the tool?

@ashishdhingra
Copy link
Contributor

Thank you for looking into this for me. I appreciate it. I'm trying to get going with the Lambda Test Tool using an existing project, so do you think I'll just have to remove that reference and it's functionality in order to use the tool?

@coultonluke Removing that reference resolves the issue. I would have team look at this issue to see if something could be done, before deciding to close the issue.

@coultonluke
Copy link
Contributor Author

coultonluke commented Feb 7, 2022

Are razor views generally supported when using the Lambda Test Tool even without the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation reference?

I've created a basic project in the same way and the views work completely fine when running as a normal project, but when I use the Lambda Test Tool the Views cannot be found. I've tried setting a ContentRootPath and also setting them to copy but to no avail.

Repository ==> https://github.com/coultonluke/riderlambdatest.git

image

I thought I knew a thing or two about .NET Core MVC as I use it every day, but this stuff is leaving me stumped cause even basic stuff isn't working. Perhaps it's my own fault for sticking with 3.1 for soo long 😂

@ashishdhingra
Copy link
Contributor

{ "httpMethod": "GET", "path": "/api/Home" }

@coultonluke I'm unsure why you are using Mock Lambda Test tool to test the Razor pages. Mock Lambda Test tool is ideal for testing simple Lambda functions and API requests. Example Requests dropdown in the tool provides a good reference for the JSON to be used for common requests. Normal razor pages could be tested in IIS/IIS Express environment.

@coultonluke
Copy link
Contributor Author

coultonluke commented Feb 7, 2022

Its because I'm wanting to host my existing website MVC application in AWS Lambda. When I run the lambda in AWS Lambda it returns views just fine, but I am struggling to replicate it locally using the test tool. I want to be able to debug any issues that are faced by running the LambdaEntryPoint as would be running in the real environment.

I was just looking at the code base and I was going to suggest adding an example ALB request to the list of common request types. The Amazon.Lambda.AspNetCoreServer supports ApplicationLoadBalancerFunction but there is no test request for it from what I can see? I was thinking this might be a useful pull request to add a request like the example request provided in the documentation.

I see what you're saying, but even with an API endpoint you could just use normal debugging and postman or whatever to test requests, you don't need to use the Mock Lambda Test Tool, but the test tool is intended to test it and return the response as if it were hosted in lambda?

@ashishdhingra
Copy link
Contributor

ashishdhingra commented Feb 7, 2022

provided in the documentation

@coultonluke Thanks for your reply. As pointed out earlier, Mock Lambda test tool is not suitable for testing Razor pages; local IIS/IIS Express testing could be used to test Razor pages.

As far as adding an example ALB request to the list of common request types is concerned, it could be a good candidate for feature request. Feel free to test and submit a PR for review if possible, which could then be reviewed by the team.

Also refer Lambda Test Tool Readme for additional details and Known Limitations.

@coultonluke
Copy link
Contributor Author

coultonluke commented Feb 7, 2022

Thank you again. I will look into posting a pull request.

I must be misunderstanding the need for the tool somewhat I suppose, because it seems like an odd limitation for the tool to care what is returned back from an API request as long as there is something that was returned, whether the body is HTML or JSON should it matter when you're essentially working with a web app?

The important thing for me is to be able to debug it as if it were in the lambda environment, I'm not the only one returning HTML back from a lambda surely 😐. I think the BBC have all of their sites hosted in lambda nowadays.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2022

⚠️COMMENT VISIBILITY WARNING⚠️

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.

@coultonluke coultonluke reopened this Feb 7, 2022
@coultonluke
Copy link
Contributor Author

I didn't mean to press close. I have reopened this.

@coultonluke
Copy link
Contributor Author

@ashishdhingra After some sleep I think I understand what you're saying now. Are you saying that I can still debug through the code even if I don't have the view coming back in the lambda test tool? If that's the case then I do agree, it's not that important to be able to see the response back in the blazor app really. It just surprised me that it's a limitation. Thanks again

@Pankraty
Copy link

This issues strikes us as well. We are creating a lambda function for building emails and for that, we are using Razor as a templating engine. Unfortunately, this does not work well with the test tool as we getting the same exception as described in the issue. The fix would be deeply appreciated!

@ashishdhingra ashishdhingra added queued p2 This is a standard priority issue and removed B labels Nov 2, 2022
@ashishdhingra
Copy link
Contributor

@coultonluke Good morning. I was reviewing old open issues and came across this one. The issue doesn't appear to be reproducible using latest .NET 8 AWS serverless template. Below is the code.
.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
    <!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
    <!-- Generate ready to run images during publishing to improve cold start time. -->
    <PublishReadyToRun>true</PublishReadyToRun>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="9.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.10" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="wwwroot\images\" />
  </ItemGroup>
</Project>

Startup.cs

namespace AWSServerlessNet8;

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddMvc(o => o.EnableEndpointRouting = false);
        var builder = services.AddRazorPages();
        builder.AddRazorRuntimeCompilation();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();
        app.UseMvc();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

Controllers\HomeController.cs

using Microsoft.AspNetCore.Mvc;

namespace AWSServerlessNet8.Controllers
{
    [Route("[controller]")]
    public class HomeController : Controller
    {
        [HttpGet]
        public string Index()
        {
            return "Hello";
        }
    }
}

Debugging using latest version 0.15.2 of Mock Lambda test tool and input { "httpMethod": "GET", "path": "/Home" } appears to work fine:
Screenshot 2024-10-29 at 11 21 33 AM

Please verify the same at your end and confirm if this issue could be closed.

Thanks,
Ashish

@ashishdhingra ashishdhingra self-assigned this Oct 29, 2024
@ashishdhingra ashishdhingra added the response-requested Waiting on additional info and feedback. Will move to close soon in 7 days. label Oct 29, 2024
@coultonluke
Copy link
Contributor Author

coultonluke commented Oct 30, 2024

I have just been looking at this again. I've got it set up from the template with an MVC controller, but returning HTML instead of JSON in the result still results in an error when using the test tool.

image

image

I want to return HTML, because I am hosting a website in lambda, as previously discussed, it seems like an odd limitation for it not to work just because it's an MVC controller and HTML is returned, when it's just a string returned in the "body" property of the JSON. The body should be able to be any string, whether it's HTML or JSON.

Thanks for looking into this.

@coultonluke
Copy link
Contributor Author

coultonluke commented Oct 30, 2024

Just so I'm clear on it. I can confirm that the inclusion of that Nuget package no longer causes and error when calling an API controller. So that's good!

But returning a view response from an MVC controller results in an error.

@ashishdhingra
Copy link
Contributor

@coultonluke Thanks for your response. As mentioned earlier in #1075 (comment), the Lambda Test Tool is suitable for testing simple Lambda functions and API requests. From your error stack trace, looks like ASP.NET Razor engine is unable to find the assembly, perhaps because the current directory is the Lambda tools installation directory. We could try setting the current directory to project directory, but unsure if it would work due to the limitation mentioned in #1482 (comment), where we cannot create more than one AppDomain in .NET Core and later.

I would advise you to open a new feature request mentioning all the details which could be reviewed with the team.

Thanks,
Ashish

@ashishdhingra ashishdhingra added response-requested Waiting on additional info and feedback. Will move to close soon in 7 days. and removed response-requested Waiting on additional info and feedback. Will move to close soon in 7 days. labels Oct 30, 2024
@coultonluke
Copy link
Contributor Author

Sorry to be a pain, I hope this comes across the right way - but surely the point in the test tool is be able to run any endpoint and to see the response as if it were running in the AWS lambda environment?

If I return a random string from it, or HTML, the string shouldn't matter, right? When you return an MVC response from a lambda, you'd still want to see the response that the lambda will return. Whether that be headers, a HTML string or base64 etc etc. If it would work in lambda, then it should work in the test tool right?

As mentioned I will take your advice and raise another ticket if you don't think it's covered within this one.

@ashishdhingra
Copy link
Contributor

Sorry to be a pain, I hope this comes across the right way - but surely the point in the test tool is be able to run any endpoint and to see the response as if it were running in the AWS lambda environment?

If I return a random string from it, or HTML, the string shouldn't matter, right? When you return an MVC response from a lambda, you'd still want to see the response that the lambda will return. Whether that be headers, a HTML string or base64 etc etc. If it would work in lambda, then it should work in the test tool right?

As mentioned I will take your advice and raise another ticket if you don't think it's covered within this one.

@coultonluke I understand the concern, but the error is thrown by ASP.NET runtime unable to find assemblies and the possible reason might be the design of Lambda Test Tool where it loads project assemblies at runtime. There is some work being done to make test tool better, hence it would be better to open a new feature request to get it reviewed by the team. We would look forward for the feature request.

Thanks,
Ashish

Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. module/lambda-test-tool p2 This is a standard priority issue queued response-requested Waiting on additional info and feedback. Will move to close soon in 7 days.
Projects
None yet
Development

No branches or pull requests

3 participants