RazorLight.Compilation Exception: Failed to compile generated Razor template

2.5k Views Asked by At

I'm creating a .NET 5 worker service app that watches few other apps and sends email when required. I'm using FluentEmail to send those emails and everything works fine, until I deploy the app.

When I deploy the app and it attempts to send an email, it throws this exception:

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.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (3:10) The type 'Type' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (35:37) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (38:66) 'GeneratedTemplate.ExecuteAsync()': return type must be 'Task' to match overridden member 'TemplatePageBase.ExecuteAsync()'
- (38:66) The type 'Task' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (40:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (41:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (42:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (43:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (53:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (69:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (84:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (44:19) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (92:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (47:20) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (100:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (50:20) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (108:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (53:19) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (116:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (124:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
See CompilationErrors for detailed information
   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 ---
   at RazorLight.EngineHandler.CompileTemplateAsync(String key)
   at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at FluentEmail.Razor.RazorRenderer.ParseAsync[T](String template, T model, Boolean isHtml)
   at FluentEmail.Razor.RazorRenderer.FluentEmail.Core.Interfaces.ITemplateRenderer.Parse[T](String template, T model, Boolean isHtml)
   at FluentEmail.Core.Email.UsingTemplateFromFile[T](String filename, T model, Boolean isHtml)
   at WatchDog.Services.NotificationService.SendEmailAsync[TModel](String subject, String fileName, TModel model) in C:\Users\SomeOne\source\repos\WatchDog\WatchDog\Services\NotificationService.cs:line 41

My setup looks like this:

Views Folder References
Views Folder

I added the Views folder and please note that this is a .NET 5 Worker Service project (if that matters instead of it being some Web project).

Program.cs file:

Inside the ConfigureServices, I've added the RazorRenderer as:

//Set email service using FluentEmail
 services.AddFluentEmail("[email protected]")
 .AddRazorRenderer(@$"{Directory.GetCurrentDirectory()}/Views/")
 .AddSmtpSender("smtp.somesmtp.com", 25)
 .AddSmtpSender(new System.Net.Mail.SmtpClient() { });
NotificationService.cs file:
private async Task SendEmailAsync<TModel>(string subject, TModel model)
{
    try
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var email = await scope.ServiceProvider.GetRequiredService<IFluentEmail>()
                    .To(string.Join(";", _emailRecipients))
                    .Subject(subject)
                    .UsingTemplateFromFile("./Views/Emails/SomeReport.cshtml", model)
                    .SendAsync();
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Failed to send email. Check exception for more information.");
    }
}
SomeReport.cshtml file:

SomeReport.cshtml is inside Views\Emails\SomeReport.cshtml which looks like this:

@using System.Collections.Generic;
@using WatchDog.Models;

@model IEnumerable<SomeReport>
@{
    Layout = "./Shared/_Layout.cshtml";
}

@* Work with the Model here... *@
_Layout.cshtml file:

_Layout.cshtml is inside Views\Shared\_Layout.cshtml which looks like this:

@* Some common layout styles here *@
@RenderBody()
WatchDog.csproj file:

I've also added PreserveCompilationContext and PreserveCompilationReferences:

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <PreserveCompilationReferences>true</PreserveCompilationReferences>
</PropertyGroup>

I've looked at everywhere and still haven't found a solution to this. Please help.

Thanks!

2

There are 2 best solutions below

0
user6751066 On BEST ANSWER

I had the exact same issue, but only within my published application. While debugging the worker service i didn't get the error message.

What fixed it for me was removing the p:PublishTrimmed=true property from the dotnet publish command.

For the sake of completeness, that's how my .csproj file looks like:

<PropertyGroup>
  <PreserveCompilationReferences>true</PreserveCompilationReferences>
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
  <MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>

References:

0
Digiman On

I am also had the problem with it during development of the Azure Function to send the emails with MailKit and render with RazorLight.

Solved this by searching and looking for the answers here (I didn't find a lot of info here, to be honest).

I found one helpful discussion about this - https://github.com/toddams/RazorLight/discussions/483 - about using function V4 and RazorLight.

The final solution was to include some properties to *.csproj file and now it works locally fine.

<PropertyGroup>
  <TargetFramework>net6.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <PreserveCompilationReferences>true</PreserveCompilationReferences>
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
  <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>

One more additional note: wen we run function locally it runs from func.exe process from Azure Function Core Tools, so executed and entry assembly will be wrong - not from the project but from core tools. To solve it need to use configuration for RazorLight - SetOpetatingAssembly():

var builder = new RazorLightEngineBuilder()
            .SetOperatingAssembly(typeof(EmailService).Assembly) // <-- this one can help
            .UseProject(project) // in my case I am using custom project to read emplate from the Azure Blob storage!
            .UseMemoryCachingProvider()
            .Build();

So this settings can help to render properly Razor views in Azure Function.

Hope it can help to solve the issue.