Antaris / RazorEngine

Open source templating engine based on Microsoft's Razor parsing engine
http://antaris.github.io/RazorEngine
Other
2.14k stars 577 forks source link

rootDirectoryPath Null exception is thrown in Azure Function v2 with custom Template manager (Razor.Core.NetCore) #536

Open vshandra opened 5 years ago

vshandra commented 5 years ago

Exception is thrown from Razor .Net Core in Azure Functions v2 with custom Template manager that loads template content from DB: Value cannot be null or an empty string. Parameter name: rootDirectoryPath

Code:

public string Render(string templateName, object model)
        {
            this.Compile(templateName);
            var result = this.razorEngine.Run(templateName, null, model);
            return result;
        }

        private void Compile(string templateName)
        {
                    if (!this.razorEngine.IsTemplateCached(templateName, null))
                    {
                        this.razorEngine.Compile(templateName);
                    }
        }

Razor initialization:

 var templateServiceConfiguration = new TemplateServiceConfiguration
            {
                ReferenceResolver = new RazorReferenceResolver(),
                TemplateManager = CreateTemplateManager(configurationManager)
            };

            var razorEngineService = RazorEngineService.Create(templateServiceConfiguration);

Template is loaded from custom source:

public ITemplateSource Resolve(ITemplateKey key)
        {
               ...
            return new LoadedTemplateSource(templateContent, key.Name);
        }

Looks like the path is returned as empty string in CompilerServiceBase.cs:

   string path = null;
                if (string.IsNullOrWhiteSpace(context.TemplateContent.TemplateFile))
                {
                    path = Directory.GetCurrentDirectory();
                }
                else
                {
**// This code path is executed and returns empty string or null**

                    path = Path.GetDirectoryName(context.TemplateContent.TemplateFile);
                }

Also here

 if (string.IsNullOrWhiteSpace(context.TemplateContent.TemplateFile))
                {
                    var doc = projectEngine.Process(new InMemoryRazorProjectItemWrapper(context.TemplateContent.Template));
                    result = GenerateCodeFile(doc);
                }
                else
                {
                   **// This code path is executed but we suppose that the projectEngine.Process(new InMemoryRazorProjectItemWrapper(context.TemplateContent.Template)); should be processed**

                    var item = razorProject.GetItem(context.TemplateContent.TemplateFile);
                    var doc = projectEngine.Process(new FileSystemRazorProjectItemWrapper(item));
                    result = GenerateCodeFile(doc);
                }

StackTrace:

  at Microsoft.AspNetCore.Razor.Language.RazorProjectFileSystem.Create(String rootDirectoryPath)
   at RazorEngine.Compilation.CompilerServiceBase.GetGeneratorResult(IEnumerable`1 namespaces, TypeContext context)
   at RazorEngine.Compilation.CompilerServiceBase.GetCodeCompileUnit(TypeContext context)
   at RazorEngine.Roslyn.CSharp.RoslynCompilerServiceBase.CompileType(TypeContext context)
   at RazorEngine.Templating.RazorEngineCore.CreateTemplateType(ITemplateSource razorTemplate, Type modelType)
   at RazorEngine.Templating.RazorEngineCore.Compile(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.RazorEngineService.CompileAndCacheInternal(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.RazorEngineService.Compile(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.DynamicWrapperService.Compile(ITemplateKey key, Type modelType)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Compile(IRazorEngineService service, String name, Type modelType)
   at QuickHelp.Engagement.TemplateBuilder.TemplateEngine.Compile(String templateName) in D:\srcs\QuickHelp.Engagement.Shared\QuickHelp.Engagement.TemplateBuilder\TemplateEngine.cs:line 40
   at QuickHelp.Engagement.TemplateBuilder.TemplateEngine.Render(String templateName, Object model) in D:\srcs\QuickHelp.Engagement.Shared\QuickHelp.Engagement.TemplateBuilder\TemplateEngine.cs:line 21
   at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   at QuickHelp.Engagement.SendEmail.Emails.EmailService.GetEmailBody(String model, String template, String customTemplate, Nullable`1 version) in D:\srcs\QuickHelp.Engagement.SendEmail\QuickHelp.Engagement.SendEmail.Emails\EmailService.cs:line 274
   at QuickHelp.Engagement.SendEmail.Emails.EmailQueueModelProcessor.SendAppointmentMessage(BaseEmailModel emailQueueModel, ISmtpClient smtpClient) in D:\srcs\QuickHelp.Engagement.SendEmail\QuickHelp.Engagement.SendEmail.Emails\EmailQueueModelProcessor.cs:line 78
   at QuickHelp.Engagement.SendEmail.Func.SendAppointmentFunc.Run(String myQueueItem, ExecutionContext context) in D:\srcs\QuickHelp.Engagement.SendEmail\QuickHelp.Engagement.SendEmail.Func\SendAppointmentFunc.cs:line 31
marioilitio commented 4 years ago

I have exactly the same issue. I am migrating from netframework/webjobs to net.core/Az-Functions and the code working on netframework is not working on netcore because of this error. Plz help. Thx

MISTikus commented 2 years ago

I guess this is the same problem as mine... here is the reason: CompilerServiceBase.cs

        private string GetGeneratorResult(IEnumerable<string> namespaces, TypeContext context)
        {
                ...
                string path = null;
                if (string.IsNullOrWhiteSpace(context.TemplateContent.TemplateFile))
                {
                    path = Directory.GetCurrentDirectory();
                }
                else
                {
                    path = Path.GetDirectoryName(context.TemplateContent.TemplateFile);
                }
                var razorProject = RazorProjectFileSystem.Create(path);
                ...

So, I think that for now TemplateFile has to contain at least "./" for path variable not to be empty