toddams/RazorLight

Error compiling: The type or namespace name 'Razor' does not exist in the namespace 'RazorLight'...

Opened this issue · 11 comments

Describe the bug
When attempting to compile a string template and a complex model, we get the error:

Failed to compile generated Razor template:
- (3:29) The type or namespace name 'Razor' does not exist in the namespace 'RazorLight' (are you missing an assembly reference?)

To Reproduce

  • .Net Framework 4.7.2
  • Project is an ASP.NET solution with .cshtml views, which work fine
  • Use a non-trivial string template with references to C# POCOs (a simple "Hello World" string works fine)

Expected behavior

  • The CompileRenderStringAsync() function returns the result

Information (please complete the following information):

  • OS: Windows 10 (dev environment)
  • Platform: .NET Framework 4.7.2
  • RazorLight version: 2.0.0-rc.3 (latest)
  • Are you using the OFFICIAL RazorLight package? https://www.nuget.org/packages/razorlight (I installed it with Package Manager as recommended on your main page)
  • Visual Studio version: VS Professional 2019 Version 16.8.2 (latest)

Additional context
Clearly the library is referenced - there would be no way to call the .CompileRenderStringAsync() method otherwise. And it does build and compile fine.

I tried these things:

  1. Added the <PropertyGroup> settings you mentioned (all of them) in the ASP.NET .csproj file. It didn't change anything - and also those might apply only to .Net Core?

I don't think this is an issue with your library necessarily - it's just unclear how to figure this out.

To Reproduce

  • .Net Framework 4.7.2
  • Project is an ASP.NET solution with .cshtml views, which work fine
  • Use a non-trivial string template with references to C# POCOs (a simple "Hello World" string works fine)

I need to dig into this a bit, but we started getting clever with how we handled different target frameworks in this commit: d56fd12 - so it is possible there is a bug for .NET Framework 4.7.2 since we're targeting netstandard2.0 since that commit. I've been thinking recently that may have been a mistake, but haven't had time to tinker with it.

To confirm, there are two .CompileRenderStringAsync() methods in RazorLight - one on the EngineHandler and one on RazorLightEngine. Which one are you using?

Can you post a quick repro, like this?

var engine = new RazorLightEngineBuilder()
	.UseEmbeddedResourcesProject(typeof(Program))
	.UseMemoryCachingProvider()
	.Build();

var model = new SchoolForAnts();
string result = await engine.CompileRenderStringAsync<SchoolForAnts>("SchoolForAnts", "@Model.Value", model);

Sure thing, thanks so much for checking this out. Here's what we have so far.

public static string Execute(string content, object model)
{
    var engine = new RazorLightEngineBuilder()
        // We get NREs at .Build() w/o both of these lines
        // Note: this is a random object from the project that holds our POCOs - not the currently executing project
        // Note 2: this is an ASP.NET app so there's no Program object
        .UseEmbeddedResourcesProject(typeof(OurWebApp.Data.Order))
        .SetOperatingAssembly(typeof(OurWebApp.Data.Order).Assembly)
        .UseMemoryCachingProvider()
        .Build();
    //
    // Causes error: Failed to compile generated Razor template:
    //      -(3:29) The type or namespace name 'Razor' does not exist in the namespace 'RazorLight' (are you missing an assembly reference?)
    //
    string result = Task.Run(() => engine.CompileRenderStringAsync("templateKey", content, model)).Result;
}

@jbaumbach

I spent 4.5 hours today fixing the solution so that it explicitly covers .NET 4.7.2 in RazorLight.Tests.csproj #407

Can you please add a failing test once I merge this into master branch?

When I did the tests, only one failed after I added SetOperatingAssembly: Constructor_SetDefines. I am still not sure why this behavior is different in .NET Framework vs. NET Core, and I tried decompiling the libraries to figure it out, but nothing made sense as to why this happens.

Great, thank you so much John. I will test as soon as you merge.

I'm a little stuck and I don't know why exactly this worked in Travis CI with Ubuntu Bionic but is failing on GitHub (also Ubuntu Bionic). It has something to do I think with shadow copied test assemblies not copying over the Assets/Files folder in order to run the FileSystemRazorProject tests. The error I get is:

[xUnit.net 00:00:04.8184942]     RazorLight.Tests.Integration.RendererCommonCasesTests.Should_Fail_When_Required_Section_Is_Missing [FAIL]
[xUnit.net 00:00:04.8198416]       System.IO.DirectoryNotFoundException : Root directory C:\Users\runneradmin\AppData\Local\Temp\c2fc666c-2964-4d75-8976-d1deed540e76\c2fc666c-2964-4d75-8976-d1deed540e76\assembly\dl3\a151d461\0504fbde_a2e2d601\Assets\Files not found

I forked Andrew Lock's blog-examples repo and set-up a similar GitHub action for his XunitTheoryTests folder, here: https://github.com/jzabroski/blog-examples/actions/runs/461816253 - and it all works fine. It's also annoying that most CI/CD tools don't display ITestOutputHelper output unless the test fails. The big difference between what he is doing and what I was doing is he is using Path.GetRelativePath (which is only available on .NET Core and .NET 5+).

It seems as if, if we're running on Windows, we should use Directory.GetCurrentDirectory(), but if we're running on Linux/Mac, we should use this.GetType().Assembly.Location. But my tragic flaw is I want to understand why this is so different.

Ugh - think I figured it out. dotnet/runtime#29470 - Path.GetDirectoryName is dependent on which OS you run it on and what input format the path is in. The path must be compliant with the OS you run it on. But .NET renders Assembly.Location using Windows rules, I guess, and that value is not normalized to the OS.

Well, that sounds pretty complicated but glad you got to the bottom of it. Let me know when build RazorLight 2.0.0-rc.4 is ready and I'll check it out.

Hey @jzabroski by any chance do you have an ETA of when the correction for this issue will be released?

@joaolongo As far as I'm aware there are no issues. I explicitly added test coverage. Please submit a PR for a failing test and I can fix it pretty quickly. The remaining problem is I get incomplete repros.

0Neji commented

Hi @jzabroski

I'm running in to a similar error message when trying to use RazorLight on an Umbraco project.

I've got a project you can check out at: https://github.com/0Neji/UmbracoRazorStaticHtml

To recreate the error:

  1. Checkout and run the solution in debug
  2. Place a breakpoint at line 51 in HtmlGeneration.cs - https://github.com/0Neji/UmbracoRazorStaticHtml/blob/main/UmbracoStaticHtml/UmbracoStaticHtml/Components/HtmlGeneration.cs#L51
  3. Go to the Umbraco login area: https://localhost:44324/umbraco
  4. Login with following details: Username: test@papermoon.io Password: @Test123456
  5. Click on "Home"
  6. Click on "Save and Publish"

I've also put together a short video of the process: https://papermoonio-my.sharepoint.com/:v:/g/personal/ben_papermoon_io/EWheNegHzelKq6uQNALB-2oBU4MhvtEBPBbkjzfzXUhJzQ

Thanks,

Ben

This issue caused by
.SetOperatingAssembly(typeof(OurWebApp.Data.Order).Assembly)

If your model is dynamic object, it will give you above errors.
Be careful if you just simply remove this, RazorLightEngine.Build() will try to get the Assembly
Assembly assembly = operatingAssembly ?? Assembly.GetEntryAssembly(); RoslynCompilationService compilationService = new RoslynCompilationService(referenceManager, assembly);

This will cause null value exception if you run your code in unit test and cross projects.