We use Razorlight (via FluentEmail) to generate emails (strings) from cshtml files (razor templates).
After upgrading from .netcore 2.2 to 3.1 the code works and tests work through `dotnet test`, but fail when run under ncrunch.
I've made a small reproduction here:
https://github.com/danzel/ncrunch-razorlight
You can run it, navigate to https://localhost:5001/weatherforecast and you'll end up at some plain text html with "Heading: ExpectedString".
You can also run `dotnet test` in the solution folder and the test will pass.
But when run under ncrunch you end up with
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
RazorLight.Compilation.TemplateCompilationException: Failed to compile generated Razor template:
- (3:35) The type 'Attribute' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
- (3:63) Predefined type 'System.String' is not defined or imported
.... lots more ....
Razorlight needs these new options set in the csproj, maybe ncrunch isn't respecting them?
Thanks for sharing this issue and for taking the time to create a sample solution that reproduces it. I've spent today pulling apart the projects involved (Razorlight, FluentEmail, etc) to understand what is happening here and what can be done about it.
The results of this have not been particularly encouraging.
Razorlight makes a call to the DependencyContext of the top-level project (i.e. your test project) to obtain a list of all compile-time references used in the environment from the .deps file. It then uses this as input to the roslyn compiler to compile the views that get handed downstream. This is problematic for NCrunch because the manner in which we build projects is very different to that of a foreground VS build, and we simply don't have the same dependency data available. Consequently the razor compile action fails because it cannot find compile-only references (such as System.Runtime).
In theory, it's possible for us to solve this problem in NCrunch by sifting the raw .deps and propagating compile-time information upwards through the structure. We already do this for runtime references, as otherwise the runtime loader won't let us build a test environment. However, it's taken months of excruciating work to get the dependency structure in a state where the runtime loader can reliably roll with it ... then months more when .NET Core 3 was released and the whole thing moved underneath us again. I presently see no way we can resolve this issue in NCrunch without massive investment of time and a huge risk of breaking the whole system for a good number of users .. which we definitely do not want to do at a time of global crisis.
So in summary, we cannot support this use case.
However, there is an opportunity for a workaround. Razorlight provides you the ability to specify the compile-time references manually through the RazorLightEngineBuilder.AddMetadataReferences method. Unfortunately, all ability to manipulate this is controlled by the FluentEmail library, so you'll need to break out your own class implementing FluentEmail.Razor.ITemplateRenderer that can specify the required references to RazorLightEngineBuilder. If you pass it the references needed to compile the templates, in theory you should be able to use NCrunch with these libraries under .NET Core 3.1.