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

Cannot render template in docker container #336

Open
darind opened this issue Apr 16, 2020 · 3 comments
Open

Cannot render template in docker container #336

darind opened this issue Apr 16, 2020 · 3 comments

Comments

@darind
Copy link

darind commented Apr 16, 2020

Describe the bug

I am trying to render a razor template in a docker container using .NET Core 3.1.

Getting the following error at runtime:

Unhandled exception. System.InvalidOperationException: Cannot find reference assembly 'Microsoft.AspNetCore.Antiforgery.dll' file for package Microsoft.AspNetCore.Antiforgery.Reference
   at Microsoft.Extensions.DependencyModel.Resolution.ReferenceAssemblyPathResolver.TryResolveAssemblyPaths(CompilationLibrary library, List`1 assemblies)
   at Microsoft.Extensions.DependencyModel.Resolution.CompositeCompilationAssemblyResolver.TryResolveAssemblyPaths(CompilationLibrary library, List`1 assemblies)
   at Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths(ICompilationAssemblyResolver resolver, List`1 assemblies)
   at Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths()
   at RazorLight.Compilation.DefaultMetadataReferenceManager.<>c.<Resolve>b__10_0(CompilationLibrary library)
   at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
   at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly, DependencyContext dependencyContext)
   at RazorLight.Compilation.DefaultMetadataReferenceManager.Resolve(Assembly assembly)
   at RazorLight.Compilation.RoslynCompilationService.EnsureOptions()
   at RazorLight.Compilation.RoslynCompilationService.get_ParseOptions()
   at RazorLight.Compilation.RoslynCompilationService.CreateSyntaxTree(SourceText sourceText)
   at RazorLight.Compilation.RoslynCompilationService.CreateCompilation(String compilationContent, String assemblyName)
   at RazorLight.Compilation.RoslynCompilationService.CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
   at RazorLight.Compilation.RazorTemplateCompiler.CompileAndEmit(RazorLightProjectItem projectItem)
   at RazorLight.Compilation.RazorTemplateCompiler.OnCacheMissAsync(String templateKey)
--- End of stack trace from previous location where exception was thrown ---
   at RazorLight.EngineHandler.CompileTemplateAsync(String key)
   at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
   at TestApp.Program.Main(String[] args)
   at TestApp.Program.<Main>(String[] args)

To Reproduce

Create a new .NET Core console application and add reference to the RazorLight NuGet. Also add the following to the corresponding .csproj:

<PropertyGroup>
    <PreserveCompilationReferences>true</PreserveCompilationReferences>
    <PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>

Render a simple template in the app:

using System;
using System.Threading.Tasks;
using RazorLight;

namespace TestApp
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var engine = new RazorLightEngineBuilder()
                .UseEmbeddedResourcesProject(typeof(Program))
                .UseMemoryCachingProvider()
                .Build();

            var message = "Hello @Model.Name";
            var content = await engine.CompileRenderStringAsync(message, message, new
            {
                Name = "world",
            });

            Console.WriteLine(content);
        }
    }
}

To build the docker container use the following Dockerfile:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY *.sln .
COPY TestApp/*.csproj ./TestApp/
RUN dotnet restore ./TestApp/TestApp.csproj -r alpine-x64

# copy everything else and build app
COPY TestApp/. ./TestApp/
WORKDIR /source/TestApp

RUN dotnet publish \
       -c Release \
       -o ./publish \
       -r alpine-x64 \
       --self-contained true \
       --no-restore \
       /p:PublishTrimmed=true \
       /p:PublishSingleFile=true \
       /p:UseAppHost=true

FROM alpine:3.9.4
# Add some libs required by .NET runtime
RUN apk add --no-cache libstdc++ libintl

# Copy
WORKDIR /app
COPY --from=build /source/TestApp/publish ./

ENTRYPOINT [ "./TestApp" ]

Then build the image:

docker build -t test-app .

And run:

docker run -e DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 test-app

Expected behavior

The application runs without errors and prints "Hello world".

Information (please complete the following information):

  • OS: Alpine Linux 3.9.4
  • Platform .NET Core 3.1
  • RazorLight version: 2.0.0-beta7
  • Are you using the OFFICIAL RazorLight package? https://www.nuget.org/packages/razorlight: Yes
  • Visual Studio version: Visual Studio for Mac 8.5.3 (build 16)

Additional context

If I remove the /p:PublishTrimmed=true and /p:PublishSingleFile=true parameters when compiling the app, then it works fine:

RUN dotnet publish \
       -c Release \
       -o ./publish \
       -r alpine-x64 \
       --self-contained true \
       --no-restore \
       /p:UseAppHost=true

So it looks like the IL linker is stripping some information that RazorLight depends on.

@jzabroski
Copy link
Collaborator

Thanks. This will help #299 a lot. A little off-topic for your issue but, since you're here: Is alpine-x64 capable of testing Unicode features? I thought it wasn't? And maybe that's why you're also passing DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1?

@darind
Copy link
Author

darind commented Apr 20, 2020

@jzabroski, what are you referring to as Unicode features? I am using DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 because my app doesn't need to support any other cultures and I am using a slimmed down version of alpine-x64 which doesn't include the corresponding dependencies.

@bvmeer
Copy link

bvmeer commented May 25, 2020

Any update on this issue? I have the same issue, when using the RazorLight package within a REST API to send a email based on razor templates. (.net core 3.1)
The issue resolved when adding a reference to nuget package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants