toddams / RazorLight

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

CompileRenderStringAsync cannot find included template #344

Closed Vincentvwal closed 4 years ago

Vincentvwal commented 4 years ago

Running latest Beta with .Net standard 2.1 we are implementing RazorLight, however have run into an issue with including templates. We are running a pre-compile of our templates by getting them all and running CompileRenderStringAsync.

var typeName = string.Concat(TemplateModelsNameSpace, template.ModelType);
var type = Type.GetType(typeName);
var instance = Activator.CreateInstance(type) as Email;
await razorEngine.CompileRenderStringAsync(typeName, template.UnparsedTemplate, instance);

This works for single templates, however when including an header for example, it throws the error RazorLight.TemplateNotFoundException: 'Project can not find template with key Header.cshtml' This also happens if we first compile the Header and then the template.

We initiate the RazorLight in the following way

razorEngine = new RazorLightEngineBuilder().UseEmbeddedResourcesProject(typeof(IAmAssembly).Assembly).UseMemoryCachingProvider().Build();

All templates share a generic Email class and are specified on a template basis, so NewPasswordEmail has a NewPasswordEmail as a model and includes the Email base class.

Any idea how to solve this within RazorLight?

jzabroski commented 4 years ago

When you say include a header do you mean using sections?

Vincentvwal commented 4 years ago

No i am including these using @{await IncludeAsync("Header.cshtml", Model);} This header does not only contain some information, but also the initial markup of the email like styles header data and the beginning of the body

fhucko commented 4 years ago

At first glance, I would say remove ".cshtml" from IncludeAsync call.

Vincentvwal commented 4 years ago

Managed to find the issue, CompileRenderStringAsync creates the ITemplate with the key of type Email and not of type header as i has expected. So when it is a shared template (as this one is) i have set the templatename based on the name of the cshtml itself instead of the model.