Razorlight: Can't load metadata ... this time in Azure Functions

Created on 27 Oct 2018  ·  4Comments  ·  Source: toddams/RazorLight

Describe the bug
I'm opening this because I'm experiencing the same behavior as #127 but this time in an Azure Functions app:

Can't load metadata reference from the entry assembly. Make sure PreserveCompilationContext is set to true in *.csproj file

To Reproduce
Try the following Azure Function (using Azure Functions v2):

        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            var engine = new RazorLightEngineBuilder()
                .UseMemoryCachingProvider()
                .Build();

            var template = "Hello, @Model.Name";
            var model = new ViewModel { Name = "Adrian" };

            var result = await engine.CompileRenderAsync("templateKey", template, model);

            return new OkObjectResult(result);
        }

Information (please complete the following information):

  • OS: Windows 10
  • Platform .Net Core 2.1
  • RazorLight version 2.0-beta1

Additional context
I have PreserveCompilationContext true in the functions csproj file … but I suspect that this is probably not what's meant by the entry assembly. It looks as if there a number of infrastructure assemblies involved before my function ever gets called.

Most helpful comment

Just want to confirm the above by @drhkocher as that worked for me too but on Azure App Service. I was previously getting the following error:

System.InvalidOperationException: Cannot find compilation library location for package 'Microsoft.AspNet.WebApi.Client'

My setup uses RazorLight for emails, I have my "Mailer" class that builds the Razor templates in a separate library to my main application. This separate library uses CSHTML files as embedded resources.

In this library's "csproj" file, I needed <PreserveCompilationContext>true</PreserveCompilationContext> - didn't need any of the other settings in there that you might see mentioned. I had to use the same "unofficial" beta 1.3 with .SetOperatingAssembly(Assembly.GetExecutingAssembly()) on the RazorLightEngineBuilder.

The reason for the unofficial beta is the NullReferenceException thrown from RazorLight.Compilation.DefaultMetadataReferenceManager in Resolve when you call SetOperatingAssembly with certain assemblies (like the currently executing one). Don't know where the source code is of the unofficial beta so take it with a grain of salt that it isn't potentially malicious.

As for _why_ this works - I have no freaking idea. My templates don't reference WebApi and my main application (an ASP.NET Core 2.2 site) works fine as it is so... 🤷‍♀️

Anyway, that took me hours of trial and error to fix as it worked fine without it on my local machine. Hopefully it saves someone else a bunch of time!

I don't believe this bug should be closed as it currently stands. The above issue as detailed still exists with SetOperatingAssembly(Assembly.GetExecutingAssembly()). Can we please get the fix which exists on the Unofficial packaged moved up to the Official package?

All 4 comments

Also having this same issue...
.NET Standard 2.0
Azure Function v2

Same Problem: .NET Standard 2.0, Azure Function 2.0
Since the entry assembly is coming from the Azure Functions runtime, I cannot control this setting there, so I need a workaround...

UPDATE: I made it work with the following workaround:

  1. I used .SetOperatingAssembly(currentAssembly) to use my own assembly (with PreserveCompilationContext = true) as a starting point. By setting the assembly here it does not use the entry assembly (which is part of Microsoft Azure).

  2. I had to switch from Beta1 to the "unofficial" beta1.3 because otherwise I got a NullPointerException.

Maybe that could be added to the documentation.

Just want to confirm the above by @drhkocher as that worked for me too but on Azure App Service. I was previously getting the following error:

System.InvalidOperationException: Cannot find compilation library location for package 'Microsoft.AspNet.WebApi.Client'

My setup uses RazorLight for emails, I have my "Mailer" class that builds the Razor templates in a separate library to my main application. This separate library uses CSHTML files as embedded resources.

In this library's "csproj" file, I needed <PreserveCompilationContext>true</PreserveCompilationContext> - didn't need any of the other settings in there that you might see mentioned. I had to use the same "unofficial" beta 1.3 with .SetOperatingAssembly(Assembly.GetExecutingAssembly()) on the RazorLightEngineBuilder.

The reason for the unofficial beta is the NullReferenceException thrown from RazorLight.Compilation.DefaultMetadataReferenceManager in Resolve when you call SetOperatingAssembly with certain assemblies (like the currently executing one). Don't know where the source code is of the unofficial beta so take it with a grain of salt that it isn't potentially malicious.

As for _why_ this works - I have no freaking idea. My templates don't reference WebApi and my main application (an ASP.NET Core 2.2 site) works fine as it is so... 🤷‍♀️

Anyway, that took me hours of trial and error to fix as it worked fine without it on my local machine. Hopefully it saves someone else a bunch of time!

Just want to confirm the above by @drhkocher as that worked for me too but on Azure App Service. I was previously getting the following error:

System.InvalidOperationException: Cannot find compilation library location for package 'Microsoft.AspNet.WebApi.Client'

My setup uses RazorLight for emails, I have my "Mailer" class that builds the Razor templates in a separate library to my main application. This separate library uses CSHTML files as embedded resources.

In this library's "csproj" file, I needed <PreserveCompilationContext>true</PreserveCompilationContext> - didn't need any of the other settings in there that you might see mentioned. I had to use the same "unofficial" beta 1.3 with .SetOperatingAssembly(Assembly.GetExecutingAssembly()) on the RazorLightEngineBuilder.

The reason for the unofficial beta is the NullReferenceException thrown from RazorLight.Compilation.DefaultMetadataReferenceManager in Resolve when you call SetOperatingAssembly with certain assemblies (like the currently executing one). Don't know where the source code is of the unofficial beta so take it with a grain of salt that it isn't potentially malicious.

As for _why_ this works - I have no freaking idea. My templates don't reference WebApi and my main application (an ASP.NET Core 2.2 site) works fine as it is so... 🤷‍♀️

Anyway, that took me hours of trial and error to fix as it worked fine without it on my local machine. Hopefully it saves someone else a bunch of time!

I don't believe this bug should be closed as it currently stands. The above issue as detailed still exists with SetOperatingAssembly(Assembly.GetExecutingAssembly()). Can we please get the fix which exists on the Unofficial packaged moved up to the Official package?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

WaltDaniels picture WaltDaniels  ·  6Comments

Hubert-Rybak picture Hubert-Rybak  ·  5Comments

btran021111 picture btran021111  ·  4Comments

dombarnes picture dombarnes  ·  7Comments

ossaltu picture ossaltu  ·  6Comments