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

AWS Toolkit for Visual Studio is unable to deploy a Blazor Web App with Interactive Render Mode WebAssembly #414

Closed
genifycom opened this issue Apr 12, 2024 · 9 comments
Labels
bug We can reproduce the issue and confirmed it is a bug.

Comments

@genifycom
Copy link

genifycom commented Apr 12, 2024

I am using all dotnet 8.

If you create a Blazor Web App with Interactive Render Mode WebAssembly then the Visual Studio template will create two projects.

The first is a Web app that can run Server Side Rendered Blazor.
The second is a cut down Blazor Webassembly App which will run Client Side rendered Webassembly.

If we create a project for AWS Serverless Application and put a project dependency on the WebAssembly client app. We can no longer Publish to AWS.

However, the MSBuild for the Blazor Web App correctly packages up the publish.

The MSBuild for the AWS app needs to do the same thing so that we can serve up the WebAssembly pieces from the AWS Serverless Application (in the Blazor Web App publish is a directory _framework containing all of the downloadable Webassembly components).

As far as the Webassembly piece is concerned, this is just downloadable content.

Note: I am not using Blazor server anywhere which requires a Websocket to work. This is just static Webassembly content.

@genifycom genifycom added the bug We can reproduce the issue and confirmed it is a bug. label Apr 12, 2024
@philasmar
Copy link

Would you be able to provide exact steps that you are taking to get to the issue? Are you trying to deploy the AWS Serverless Application using "Publish to AWS Lambda" or "Publish to AWS"? Also, in the Blazor Web App template, the main project is the server project not the client project. So if you are trying to publish or deploy, you should use the server project as the main one.

@genifycom
Copy link
Author

genifycom commented Apr 22, 2024

Please note that the Blazor Web App template changed in DotNet 8. It now generates two projects, one for Blazor server-side rendering and one for Blazor Webassembly.

Steps to create:

  1. Create a Blazor Web App BlazorWebApp1.
    In additional Information choose Interactive render mode as WebAssembly. Leave Interactivity location as "Per page/component". Include sample pages

  2. Two projects will be created.
    BlazorWebApp1 project contains the Server Side Rendered Blazor components (Home and Weather in folder Components/Pages).
    BlazorWebApp1.Client contains the Webassembly component Counter (in folder Pages).

  3. Running the BlazorWebApp1 project demonstrates the two modes. Selecting Home or Weather generates all pages from the server.
    However, selecting Counter causes the DotNet Webassembly client to be downloaded and executed on the client (see the wasm tab in Network on Chrome Dev Tools).
    Publish to a folder will complete and run from the folder include all any WASM components.

Now we want to do the same thing in AWS lambda.

  1. Create a new project AWS Serverless Application AWSServerless1 use Blueprint ASP.NET Core Web App

  2. Add a project dependency to BlazorWebApp1.Client (the same as in BlazorWebApp1)

Now attempt to Publish to AWS Lambda.

Processing CloudFormation resource AspNetCoreApi
Processing CloudFormation resource AspNetCoreFunction
Initiate packaging of . for resource AspNetCoreFunction
Executing publish command
... invoking 'dotnet publish', working folder 'C:\Dev\AITC\BlazorWebApp1\AWSServerless1\.\bin\Release\net8.0\publish'
... dotnet publish "C:\Dev\AITC\BlazorWebApp1\AWSServerless1\." --output "C:\Dev\AITC\BlazorWebApp1\AWSServerless1\.\bin\Release\net8.0\publish" --configuration "Release" --framework "net8.0" /p:GenerateRuntimeConfigurationFiles=true --runtime linux-x64 --self-contained False 
... publish:   Determining projects to restore...
... publish:   Restored C:\Dev\AITC\BlazorWebApp1\BlazorWebApp1\BlazorWebApp1.Client\BlazorWebApp1.Client.csproj (in 2.77 sec).
... publish:   Restored C:\Dev\AITC\BlazorWebApp1\AWSServerless1\AWSServerless1.csproj (in 4.4 sec).
... publish: C:\Program Files\dotnet\sdk\8.0.300-preview.24203.14\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(311,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [C:\Dev\AITC\BlazorWebApp1\AWSServerless1\AWSServerless1.csproj]
... publish: C:\Users\DHA\.nuget\packages\microsoft.net.sdk.webassembly.pack\8.0.4\build\Microsoft.NET.Sdk.WebAssembly.Browser.targets(231,5): error WASM0005: Unable to resolve WebAssembly runtime pack version [C:\Dev\AITC\BlazorWebApp1\BlazorWebApp1\BlazorWebApp1.Client\BlazorWebApp1.Client.csproj]
ERROR: The dotnet publish command return unsuccessful error code
Error packaging up project in C:\Dev\AITC\BlazorWebApp1\AWSServerless1\. for CloudFormation resource AspNetCoreFunction: ERROR: The dotnet publish command return unsuccessful error code

This may not be enough to demonstrate the whole issue, but this is my first roadblock to getting the AWS Lambda to publish. How can I see the MSBUILD script being used by AWS Publish to Lambda?

@genifycom
Copy link
Author

genifycom commented Apr 23, 2024

Project File

<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" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="wwwroot\images\" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\BlazorWebApp1\BlazorWebApp1.Client\BlazorWebApp1.Client.csproj" />
  </ItemGroup>
</Project>

This issue dotnet/aspnetcore#46711 might be related although the error message is different.

It is possible that removing --self-contained False from the dotnet publish allows this to succeed.
The publish directory looks correct with a wwwroot and _framework with the WASM components.

@genifycom
Copy link
Author

Tried adding

	`<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.4" />`

to the blazor server proj as well but no go.

Anyone have some ideas on how to make some progress?

For me, this would be a game changer. Being able to use both Blazor server-side and Blazor client-side Webassembly from the same Lambda Application.

@genifycom
Copy link
Author

genifycom commented Apr 24, 2024

Consistent when using DotNet CLI

dotnet lambda deploy-function AWSServerless1 --function-runtime dotnet8
Amazon Lambda Tools for .NET Core applications (5.1.3)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Executing publish command
... invoking 'dotnet publish', working folder 'C:\Dev\xxx\BlazorWebApp1\AWSServerless1\bin\Release\net8.0\publish'
... dotnet publish --output "C:\Dev\xxx\BlazorWebApp1\AWSServerless1\bin\Release\net8.0\publish" --configuration "Release" --framework "net8.0" /p:GenerateRuntimeConfigurationFiles=true --runtime linux-x64 --self-contained false
... publish:   Determining projects to restore...
... publish:   All projects are up-to-date for restore.
... publish: C:\Program Files\dotnet\sdk\8.0.300-preview.24203.14\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(311,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [C:\Dev\xxx\BlazorWebApp1\AWSServerless1\AWSServerless1.csproj]
... publish: C:\Users\yyy\.nuget\packages\microsoft.net.sdk.webassembly.pack\8.0.4\build\Microsoft.NET.Sdk.WebAssembly.Browser.targets(231,5): error WASM0005: Unable to resolve WebAssembly runtime pack version [C:\Dev\xxx\BlazorWebApp1\BlazorWebApp1\BlazorWebApp1.Client\BlazorWebApp1.Client.csproj]

Removing --self-contained false from the publish command, however, creates what looks like a valid publish locally.

dotnet publish --output "C:\Dev\xxx\BlazorWebApp1\AWSServerless1\bin\Release\net8.0\publish" --configuration "Release" --framework "net8.0" /p:GenerateRuntimeConfigurationFiles=true --runtime linux-x64
  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Program Files\dotnet\sdk\8.0.300-preview.24203.14\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(311,5): message NETSDK1057: You are using a preview version of .NET. See: htt
ps://aka.ms/dotnet-support-policy [C:\Dev\xxx\BlazorWebApp1\AWSServerless1\AWSServerless1.csproj]
  BlazorWebApp1.Client -> C:\Dev\xxx\BlazorWebApp1\BlazorWebApp1\BlazorWebApp1.Client\bin\Release\net8.0\BlazorWebApp1.Client.dll
  BlazorWebApp1.Client (Blazor output) -> C:\Dev\xxx\BlazorWebApp1\BlazorWebApp1\BlazorWebApp1.Client\bin\Release\net8.0\wwwroot
  AWSServerless1 -> C:\Dev\xxx\BlazorWebApp1\AWSServerless1\bin\Release\net8.0\linux-x64\AWSServerless1.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  AWSServerless1 -> C:\Dev\xxx\BlazorWebApp1\AWSServerless1\bin\Release\net8.0\publish\

@genifycom
Copy link
Author

Looks Webassembly packaging issue.

@Xiippy
Copy link

Xiippy commented Aug 17, 2024

For the good of the community, here is a CONFIRMED solution to this problem:

Key Fact:
Deployments into AWS .NET Lambda functions should be done with SelfContained=false, as "framework dependent". But your client-side webassembly project HAS TO be built as SelfContained. You must prevent the SelfContained flag from being cascaded down to the client-side project. The same goes for RuntimeIdentifier. By default, when publishing into AWS Lambda, the RuntimeIdentifier of linux-x64 is used for the client-side webassembly project too which creates some odd behaviours.

Steps to solve the issue:

  • In your server-side csproj project file, where you are referencing the client-side project, add GlobalPropertiesToRemove="SelfContained;RuntimeIdentifier" :
    <ProjectReference GlobalPropertiesToRemove="SelfContained;RuntimeIdentifier" Include="path to your client-side web assembly project">

  • In the csproj file of the client-side assembly, force SelfContained and RuntimeIdentifier to take the right values:

<PropertyGroup>
  <PublishSelfContained>true</PublishSelfContained>
  <SelfContained>true</SelfContained>
  <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
</PropertyGroup>

Now, your build with SelfContained=false (which is what AWS toolkit does) should succeed without an error, and your deployment package should be minimal in terms of size by not including the entire .net server-side runtime. The webassembly project will also be built for the browser-wasm runtime not linux-x64.

Problem solved.

@genifycom
Copy link
Author

genifycom commented Aug 23, 2024

This also works for me. In the WASM client project use

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly" TreatAsLocalProperty="SelfContained">

Then in the property Group, you can use

<SelfContained>True</SelfContained>

@Dzubrul
Copy link

Dzubrul commented Nov 26, 2024

For the good of the community, here is a CONFIRMED solution to this problem:

Key Fact: Deployments into AWS .NET Lambda functions should be done with SelfContained=false, as "framework dependent". But your client-side webassembly project HAS TO be built as SelfContained. You must prevent the SelfContained flag from being cascaded down to the client-side project. The same goes for RuntimeIdentifier. By default, when publishing into AWS Lambda, the RuntimeIdentifier of linux-x64 is used for the client-side webassembly project too which creates some odd behaviours.

Steps to solve the issue:

  • In your server-side csproj project file, where you are referencing the client-side project, add GlobalPropertiesToRemove="SelfContained;RuntimeIdentifier" :
    <ProjectReference GlobalPropertiesToRemove="SelfContained;RuntimeIdentifier" Include="path to your client-side web assembly project">
  • In the csproj file of the client-side assembly, force SelfContained and RuntimeIdentifier to take the right values:
<PropertyGroup>
  <PublishSelfContained>true</PublishSelfContained>
  <SelfContained>true</SelfContained>
  <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
</PropertyGroup>

Now, your build with SelfContained=false (which is what AWS toolkit does) should succeed without an error, and your deployment package should be minimal in terms of size by not including the entire .net server-side runtime. The webassembly project will also be built for the browser-wasm runtime not linux-x64.

Problem solved.

Thank you for this solution! I had the same problem with the WASM as part of a bigger project not on AWS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug We can reproduce the issue and confirmed it is a bug.
Projects
None yet
Development

No branches or pull requests

4 participants