Kinetq Development Group, LLC. - Liquid Pages

Liquid Pages

CI

Liquid pages is a library that uitlizes Fluid under the hood to create middleware that can be used with any web server to render liquid templates. It has a MVVM philosophy similar to Razor Pages (hence the name Liquid Pages).

Setup

Start by adding the nuget package:

nuget add Kinetq.LiquidPages

Next add all of the Liquid Pages services via this helper method:

services.AddLiquidPages()

Next you'll add middleware, which could be different based on the web server you are using. Currently there is only one build in middleware for EmbedIO (although building your own is very simple and detailed below).

Startup

For Liquid Pages to properly function Routes, Filters and Types need to be registered before attempting to render a template. In order to do that you will need to resolve the ILiquidStartup service at any point after the DI container has been created and before the application has started up. Then call the RegisterPageModels and RegisterFilters methods.

public class WebsiteStartup : IStartup
{
    private readonly ILiquidStartup _liquidStartup;

    public WebsiteStartup(ILiquidStartup liquidStartup)
    {
        _liquidStartup = liquidStartup;
    }

    public async Task Execute()
    {
        await _liquidStartup.RegisterPageModels();
        await _liquidStartup.RegisterFilters();
    }
}

Important! Even after these two steps have been completed, you'll need to setup some form of milddeware, you can view an example of that in the Sample project created here.

File Resolution

More than likely you'll want to set up your own form of file resolution for your .liquid files and assets. You can do this by creating a BasePage and overriding the GetFileProvider method:

using Kinetq.LiquidPages.Pages;
using Microsoft.Extensions.FileProviders;

namespace Kinetq.Website.Pages;

public class BasePage : LiquidPageModel
{
    public string Title { get; set; }
    public string SeoTitle { get; set; }
    public string SeoDescription { get; set; }
    public override IFileProvider GetFileProvider()
    {
#if DEBUG
        string workingDirectory = Directory.GetCurrentDirectory();
        string projectDirectory = Directory.GetParent(workingDirectory).Parent.Parent.FullName;
        return new PhysicalFileProvider(projectDirectory);

#else
        return = new EmbeddedFileProvider(typeof(BasePage).Assembly, "Kinetq.Website");
#endif
    }
}

The GetFileProvider base implementation currently defaults to a physical file provider.

LiquidPageModel

The LiquidPageModel has three overriding members:

  • OnGetAsync

  • OnPostAsync

  • GetFileProvider

Also any properties defined on the page model will be made available in the .liquid template, exposed off of the view_model object passed into the templating engine.

Here is an example of the PageModel:

[LiquidPage("^/$", "Pages/Home.liquid")]
public class HomeModel : LiquidPageModel
{
    public string Title { get; set; } = "Welcome to Home";

    public override Task OnGetAsync(LiquidRequestModel request)
    {
        // Initialize your model properties here
        // This method is called when the page is requested

        return Task.CompletedTask;
    }
}

Here is an example of the template:

{% capture page_content %}
    <h1>{{ view_model.title }}</h1>
{% endcapture %}

{% include 'Layouts/default.liquid' %}

Notice that the page model needs to be decorated with [LiquidPage("^/$", "Pages/Home.liquid")], where the first argument is regex used to define the route pattern and the second argument is the path to the liquid template. With the default GetFileProvider implementation, the route of the path will always start at the csproj root.

LiquidErrorPage

Similarly to the LiquidPage, you can define a LiquidErrorPage that will be used based on HttpStatusCode Exceptions thrown during the rendering process:

[LiquidErrorPage(HttpStatusCode.NotFound, "ErrorPages/NotFound.liquid")]
public class NotFoundModel : LiquidPageModel
{
    public string Title { get; set; } = "Page Not Found";
    public string NotFoundMessage { get; set; } = "The page you are looking for was not found.";
    public override Task OnGetAsync(LiquidRequestModel request)
    {
        // Initialize your model properties here
        // This method is called when the page is requested
        return Task.CompletedTask;
    }
}

Notice the only difference here is the attribute used to decorate the page model, specifying the status code instead of a route pattern.

Do you have more questions? Contact us

Contact us