toddams / RazorLight

Template engine based on Microsoft's Razor parsing engine for .NET Core
Apache License 2.0
1.53k stars 258 forks source link

RazorLightException: Cant load metadata... PreserveCompilationContext #127

Closed dapug closed 6 years ago

dapug commented 6 years ago

I'm getting the exception mentioned here: https://github.com/toddams/RazorLight/issues/44

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

But I opened this because none of the suggestions resolved it. Clean/Rebuild wont fix, and adding <PreserveCompilationContext>true</PreserveCompilationContext> wont fix. I am using a Core 2.0 Unit Test app, but that shouldn't be any different than a simple console app.

GoodGoodJM commented 6 years ago

Where did you add <PreserveCompilationContext>true</PreserveCompilationContext>? Try putting it in "PropertyGroup".

Like this

  <PropertyGroup>
    ...
    <PreserveCompilationContext>true</PreserveCompilationContext>
    ...
  </PropertyGroup>

I looked at the code in README and put it in ItemGroup, but it was not resolved.

I put it in PropertyGroup and I found it works.

toddams commented 6 years ago

Did it solve the issue? Waiting for feedback

dapug commented 6 years ago

Interesting. Yes that did fix it. Mine was in a PropertyGroup to begin with, but appended below other items listed in that group. I pulled it out into it's own PropertyGroup tag and it works. Cool, thanks.

So is this a hack that will always be necessary, or is there some more official fix that can be made so as not to require this manual edit?

toddams commented 6 years ago

You have to always set "PreserveCompilationContext". It was a mistake in documentation that it must be located in ItemGroup, and it's fixed now (thanks for the PR :)) Answering your question, it's not a hack but a requirement, as without this option RazorLight would not be able to compile your templates at runtime

ghost commented 6 years ago

I am trying to do this in an MSTest project for some light integration testing. As instructed, I put the PreserveCompilationContext element (with it set to true) in a property group tag (I used the existing property group tag at the top of the csproj file), however; it still gives me the error. I have run into issues similar to this in the past with unit tests. Is this something that does not work inside a unit test project and if you want to integration test compiling a razor file, you would need to test it in a console app like in the samples?

update: Just a quick sanity check for myself to ensure my code calling into RazorLight is set up properly and works as expected...

I tried pulling my DLL into a console application to confirm that it is working, (it works in the console app), this appears to be an issue with trying to run this in a unit test project.

dapug commented 6 years ago

Read my post above. You need to put it in its own isolated PropertyGroup. My unit test then worked fine.

AlexTeixeira commented 6 years ago

I have the same issue as @b1tburn3r. I add PreserveCompilationContext to true in an isolated PropertyGroup ( at the end of the file ), but my test in failing with the error :

Can't load metadata reference from the entry assembly

Can you provide a sample of working code with UnitTest ?

awernick commented 6 years ago

@AlexTeixeira @b1tburn3r I was able to get it to work by cleaning the project and rebuilding.

So the following worked

dotnet clean
dotnet test
ghost commented 5 years ago
  1. Go to project's folder location
  2. Write ".csproj" then search
  3. Find related csproj file and open it via text editor
  4. Find <PropertyGroup> node.
  5. Add <PreserveCompilationContext>true</PreserveCompilationContext> inside it.
  6. Rebuild the solution.
xxeasterxx commented 4 years ago

i did the suggestions in this thread but it's still happening on net core 3.1. Any idea?

billrob commented 4 years ago

@xxeasterxx I just found this thread and it worked for me for a worker service.exe. Be sure you put the PropertyGroup in the csproj of your executable.

jzabroski commented 4 years ago

@billrob an .exe is not a .net core executable, though. @xxeasterxx issue is with netcoreapp3.1 target framework moniker.

@xxeasterxx Sorry I missed your response, but it's generally a good idea to open a new issue rather than reply to a closed one if you're stuck. You can leave a comment here and link back to the new issue to form breadcrumbs for others to follow as a courtesy. Additionally, "it's still happening" needs more information. Thank you!

billrob commented 4 years ago

@jzabroski My intentions was to ensure it wasn't on an underlying project and added to the project that contains the entry point to the application. I had made that mistake previously.

jzabroski commented 4 years ago

@billrob Great point. I had a coworker even who did that incorrectly.

raxuser100 commented 3 years ago

I am using LinqPad which references ClassLib which in turn executes the RazorLight engine. I run into the same error:

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

I tried adding <PreserveCompilationContext> into the classlib csproj, though I know it will not work as it's not the entry point. LinqPad is the entry point!

Is there any way of getting around this error?

jzabroski commented 3 years ago

@raxuser100 From your description, you're using RazorLight.Unofficial, which isn't supported by this repository and may be quite old. nuget.org says that package was last updated last updated 6/30/2018 . Probably time for you to re-think your dependency.

raxuser100 commented 3 years ago

You are right, thanks for pointing out version issue. Would this be the correct latest version to try:

or back in 2017 I note the official release:

Both throw the same error in LinqPad.

I've raised a StockOverflow question https://stackoverflow.com/questions/67303505/linqpad-razorlight-executing-from-linqpad-throws-razorlight-razorlightexcepti

Thanks for your help,

Rakesh


From: John Zabroski @.> Sent: 28 April 2021 16:33 To: toddams/RazorLight @.> Cc: raxuser100 @.>; Mention @.> Subject: Re: [toddams/RazorLight] RazorLightException: Cant load metadata... PreserveCompilationContext (#127)

@raxuser100https://github.com/raxuser100 From your description, you're using RazorLight.Unofficial, which isn't supported by this repository and may be quite old. nuget.org says that package was last updated last updated 6/30/2018 . Probably time for you to re-think your dependency.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/toddams/RazorLight/issues/127#issuecomment-828554116, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEK5YCAA2PTB4TFEFVAJKT3TLATGFANCNFSM4EJO5CZQ.

jzabroski commented 3 years ago

Please try the beta. I was hoping to do an official version soon but I got delayed by getting the covid-19.

raxuser100 commented 3 years ago

So sorry to hear about your challenges with Covid... I do hope you are well and recovered now.

Thanks, I tried the version and it's still throwing the error.

Is there some way of utilising MetadataReference to solve this problem? Perhaps a long shot!


From: John Zabroski @.> Sent: 28 April 2021 17:31 To: toddams/RazorLight @.> Cc: raxuser100 @.>; Mention @.> Subject: Re: [toddams/RazorLight] RazorLightException: Cant load metadata... PreserveCompilationContext (#127)

Please try the beta. I was hoping to do an official version soon but I got delayed by getting the covid-19.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/toddams/RazorLight/issues/127#issuecomment-828597497, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEK5YCG3IQMWHCVQBMNFHKTTLAZ5FANCNFSM4EJO5CZQ.

mr-pankaj commented 10 months ago

Interesting. Yes that did fix it. Mine was in a PropertyGroup to begin with, but appended below other items listed in that group. I pulled it out into it's own PropertyGroup tag and it works. Cool, thanks.

So is this a hack that will always be necessary, or is there some more official fix that can be made so as not to require this manual edit?

It worked for me in .net 8

alekdavis commented 10 months ago

Setting PreserveCompilationContext fixed this issue for me, but I am wondering, if the code only uses RazorLight to merge external templates which are not part of the project/assembly, why would it need this setting? It would make sense if the code handled the internal assembly resources, but for external files, why is this dependency required?

jzabroski commented 10 months ago

@alekdavis This is not something about RazorLight but rather about how MSBuild works on Modern .NET. See: https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/6.0/preservecompilationcontext-not-set-by-default

alekdavis commented 10 months ago

Hmmm... I'm not sure what it implies. Here is my scenario: I have a unit test project (xUnit) for a .NET 6 REST-based microservice (testing controllers, service classes, and utility methods). It was working fine. Then I added unit tests (to the same unit test project) for the code (from the same microservice project) responsible for sending email notifications (it uses RazorLight to merge external email notification template files with run-time data) and the unit tests failed with the PreserveCompillationContext error. So I had to modify the unit testing project settings, and I'm not really sure why (since it just tests the functionality by merging external template files with data). I'm sure I had to add this setting to the microservice project at some point, but at least that project used RazorLight directly, so okay, it's fine. But now, I need to make the change to the project that is not even using RazorLight directly (it just calla a library that uses RazorLight). I must be missing something, but logically it does not make sense.

jzabroski commented 10 months ago

A compilation context is the transitive closure of all dependencies. Preserving it is basically like copylocal=true for every dll in the old .net framework days, but with the added twist it does it for nuget packages too. There is a bit more to it with target framework and sdk, and whether you are doing self contained deployment, but does this help you understand what is happening

alekdavis commented 10 months ago

The part I'm still puzzled with is: why is this needed if I am only working with EXTERNAL template files? It would make sense if I were merging the resources from the assemblies or Nuget packages, but my templates are stand-alone static HTML files that have nothing to do with the applciation assemblies or dependencies.

jzabroski commented 10 months ago

The dependencies would be missing, so the runtime would bomb out at runtime when it hits an IL instruction requiring a dll you did not ask MSBuild to ship.

It's actually so simple it may not be obvious.

alekdavis commented 10 months ago

But runtime is not bombing out. I mean, the application works absolutely fine without the PreserveCompilationContext setting configured. Nothing breaks until I make a RazorLight call to compile an external template. The exception comes from the DefaultMetadataReferenceManager's Resolve method which (if I'm reading the code correctly) tries to compile the application assemblies, so it can get their metadata. I suspect the metadata are needed in case the templates come from the assembly resources, right? But if the templates are stand-alone (external) files, is it really necessary?

jzabroski commented 10 months ago

That's shaky logic. You're using the word standalone file in a misleading way. It's still source code that has to be compiled. How do you expect it get compiled without the underlying compiler and reference libraries supporting asp.net tag helpers.

jzabroski commented 10 months ago

A simple analogy is that this would be like taking asp.net classic web forms uncompiled and expect Apache to magically compile it without the aspnetcompiler.exe...

alekdavis commented 10 months ago

I must admit that I do not know much about how compilation is done, so please excuse my ignorance, but my assumption is that whatever is needed for compiling a template is a dependency of the RazorLight package. The compiler and reference libraries supporting asp.net tag helpers are not part of my project, right? They are needed by RazorLight. So from what you're saying, I assume you mean that whatever dependencies RazorLight has (from other packages or system assemblies), you want to make sure they are copied locally to avoid the case, when the project compiles, but at runtime a dependency could be missing. I think I ran into a similar case a few times when some package required another package but did not bring it tranistively, so runtime errored out and I had to explictly add the missing package to the project. Am I getting it or am I still clueless? Btw, I really appreciate your package, don't know what we would've done without it.