sebastienros / fluid

Fluid is an open-source .NET template engine based on the Liquid template language.
MIT License
1.45k stars 180 forks source link

Using layout/section tags without using Fluid as ViewEngine #51

Closed pfeigl closed 5 years ago

pfeigl commented 6 years ago

We are in a pure API stack and use fluid to generate E-Mail contents. We would like to use the extensibility features of the templates (namely layout, renderbody, section and rendersection) to compose our e-mails, so my question is, whether this can be easily accomplished.

I tried simply referencing Fluid.MvcViewEngine and calling the following:

    FluidViewTemplate.TryParse(template, out var parsedTemplate, out var parseErrors)
    var context = new TemplateContext();
    // setting up context here ...
    var renderedTemplate = await parsedTemplate.RenderAsync(context);

And while the TryParse works (meaning it is recognizing the template tag), that RenderAsync call fails with

   at System.ThrowHelper.ThrowKeyNotFoundException()
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Fluid.MvcViewEngine.Tags.LayoutTag.<WriteToAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Fluid.BaseFluidTemplate`1.<RenderAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Fluid.FluidTemplateExtensions.<RenderAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at DocuSafe.Services.TemplateEngine.<RenderAsync>d__3`1.MoveNext() in C:\Development\docu-safe\DocuSafe\src\DocuSafe.Services\TemplateEngine.cs:line 45

I probably miss quite some setup which is normally done in the "AddFluid" call in the startup.

pfeigl commented 6 years ago

I actually managed to do it with the following steps:

  1. Register required services (exluding all the ViewEngine implementations)

            services.AddScoped<IOptions<FluidViewEngineOptions>, DatabaseFluidViewEngineOptions>();
            services.AddScoped<IFluidRendering, FluidRendering>();
  2. Implement IOptions. I needed this, because I get my templates from the Database and registered a custom IFileProvider in the FluidViewEngineOptions. If someone can live with the default IFileProvider, that this step can even be skipped and simply replaced by using the standard FluidViewEngineOptions.

  3. Just depend on IFluidRendering wherever needed and call the RenderAsync :)

pfeigl commented 6 years ago

Some remarks which i stumpled upon, which might make nice improvements to the library:

Possibly some of those points were intentionally chosen like that, they gave me some headaches while implementing a database based FileProvider :)

sebastienros commented 6 years ago

Might as well file issues for each of your comments.

hishamco commented 5 years ago

@pfeigl is the issue still happen?

pfeigl commented 5 years ago

I don't know to be honest, we meanwhile changed to https://github.com/lunet-io/scriban

hishamco commented 5 years ago

So this need to be closed

sebastienros commented 5 years ago

@pfeigl NOOOOOOOOOO!!! Fluid is so much better ;) Just kidding, everything @xoofx does is awesome!