DotLiquid是一个在.Net Framework上运行的模板引擎,采用Ruby的Liquid语法,这个语法广泛的用在Ruby on rails和Django等网页框架中。

DotLiquid相比于Mvc默认模板引擎Razor的好处有:

  • 因为不需要编译到程序集再载入

    • 首次渲染速度很快
    • 不会导致内存泄漏
  • 可以在任何地方使用
    • 不需要先准备WebViewPage,ViewContext等复杂的上下文对象

DotLiquid的官网是http://dotliquidmarkup.org/,开源协议是非常宽松的MS-PL。

示例代码

我创建一个使用了DotLiquid的示例Mvc项目,完整代码可以查看这里

以下的示例将以Mvc中的Action为单位,都存放在HomeController下。

最基础的使用

Template.Parse可以把字符串解析为模板对象,再使用Render把模板对象渲染为字符串。

打开页面可以看见Hello, World!

  1. public ActionResult HelloWorld()
  2. {
  3. var template = Template.Parse("Hello, {{ name }}!");
  4. var result = template.Render(Hash.FromAnonymousObject(new { name = "World" }));
  5. return Content(result);
  6. }

使用过滤器

|后面的就是过滤器,过滤器可以连锁起来使用。

escape过滤器用于做html编码,避免name中的"<"当成是html标签描画。

upcase过滤器把字符串中的字母全部转换为大写。

打开页面可以看见Hello, <WORLD>!

  1. public ActionResult HelloFilter()
  2. {
  3. var template = Template.Parse("Hello, {{ name | escape | upcase }}!");
  4. var result = template.Render(Hash.FromAnonymousObject(new { name = "<World>" }));
  5. return Content(result);
  6. }

定义过滤器

DotLiquid支持自定义过滤器,首先需要一个过滤器类型,其中的函数名称就是过滤器名称。

过滤器支持多个参数和默认参数。

  1. public class DotliquidCustomFilter
  2. {
  3. public static string Substr(string value, int startIndex, int length = -1)
  4. {
  5. if (length >= 0)
  6. return value.Substring(startIndex, length);
  7. return value.Substring(startIndex);
  8. }
  9. }

在网站启动的时候把这个过滤器注册到DotLiquid

  1. public class MvcApplication : System.Web.HttpApplication
  2. {
  3. protected void Application_Start()
  4. {
  5. // 在原有的代码下添加
  6. Template.RegisterFilter(typeof(DotliquidCustomFilter));
  7. }
  8. }

这个例子会显示Hello, orl!

  1. public ActionResult CustomFilter()
  2. {
  3. var template = Template.Parse("Hello, {{ name | substr: 1, 3 }}!");
  4. var result = template.Render(Hash.FromAnonymousObject(new { name = "World" }));
  5. return Content(result);
  6. }

使用标签

DotLiquid中有两种标签,一种是普通标签(Block),一种是自闭合标签(Tag)。

这里的assign是自闭合标签,if是普通标签,普通标签需要用end+标签名闭合。

显示内容是Hello, World!

  1. public ActionResult HelloTag()
  2. {
  3. var template = Template.Parse(@"
  4. {% assign name = 'World' %}
  5. {% if visible %}
  6. Hello, {{ name }}!
  7. {% endif %}
  8. ");
  9. var result = template.Render(Hash.FromAnonymousObject(new { visible = true }));
  10. return Content(result);
  11. }

自定义标签

这里我将定义一个自闭合标签conditional,这个标签有三个参数,如果第一个参数成立则描画第二个否则描画第三个参数。

  1. public class ConditionalTag : Tag
  2. {
  3. public string ConditionExpression { get; set; }
  4. public string TrueExpression { get; set; }
  5. public string FalseExpression { get; set; }
  6. public override void Initialize(string tagName, string markup, List<string> tokens)
  7. {
  8. base.Initialize(tagName, markup, tokens);
  9. var expressions = markup.Trim().Split(' ');
  10. ConditionExpression = expressions[0];
  11. TrueExpression = expressions[1];
  12. FalseExpression = expressions.Length >= 3 ? expressions[2] : "";
  13. }
  14. public override void Render(Context context, TextWriter result)
  15. {
  16. var condition = context[ConditionExpression];
  17. if (!(condition == null || condition.Equals(false) || condition.Equals("")))
  18. result.Write(context[TrueExpression]);
  19. else
  20. result.Write(context[FalseExpression]);
  21. }
  22. }

在网站启动时把这个标签注册到DotLiquid

  1. public class MvcApplication : System.Web.HttpApplication
  2. {
  3. protected void Application_Start()
  4. {
  5. // 在原有的代码下添加
  6. Template.RegisterTag<ConditionalTag>("conditional");
  7. }
  8. }

这个例子会显示Bar

  1. public ActionResult CustomTag()
  2. {
  3. var template = Template.Parse("{% conditional cond foo bar %}");
  4. var result = template.Render(Hash.FromAnonymousObject(new { cond = false, foo = "Foo", bar = "Bar" }));
  5. return Content(result);
  6. }

模板文件

DotLiquid也支持从文件读取模板,需要先定义一个TemplateFileSystem

  1. public class DotliquidTemplateFileSystem : IFileSystem
  2. {
  3. public string ReadTemplateFile(Context context, string templateName)
  4. {
  5. var path = context[templateName] as string;
  6. if (string.IsNullOrEmpty(path))
  7. return path;
  8. var fullPath = HttpContext.Current.Server.MapPath(path);
  9. return File.ReadAllText(fullPath);
  10. }
  11. }

设置DotLiquid使用自定义的文件系统

  1. public class MvcApplication : System.Web.HttpApplication
  2. {
  3. protected void Application_Start()
  4. {
  5. // 在原有的代码下添加
  6. Template.FileSystem = new DotliquidTemplateFileSystem();
  7. }
  8. }

再定义一个控制器基类

  1. public abstract class DotliquidController : Controller
  2. {
  3. public ContentResult DotliquidView(string path = null, object parameters = null)
  4. {
  5. // 路径为空时根据当前的Action决定
  6. if (string.IsNullOrEmpty(path))
  7. {
  8. var controller = RouteData.Values["controller"];
  9. var action = RouteData.Values["action"];
  10. path = $"~/DotliquidViews/{controller}/{action}.html";
  11. }
  12. // 根据路径读取模板内容
  13. var templateStr = Template.FileSystem.ReadTemplateFile(new Context(), "'" + path + "'");
  14. // 解析模板,这里可以缓存Parse出来的对象,但是为了简单这里就略去了
  15. var template = Template.Parse(templateStr);
  16. // 描画模板
  17. Hash templateParameters;
  18. if (parameters is IDictionary<string, object>)
  19. templateParameters = Hash.FromDictionary((IDictionary<string, object>)parameters);
  20. else
  21. templateParameters = Hash.FromAnonymousObject(parameters ?? new { });
  22. var result = template.Render(templateParameters);
  23. // 返回描画出来的内容
  24. return Content(result, "text/html");
  25. }
  26. }

现在可以在控制器中使用基于DotLiquid的模板了

  1. public ActionResult HelloTemplateFile()
  2. {
  3. return DotliquidView();
  4. }

上面会返回文件~/DotliquidViews/Home/HelloTemplateFile.html的内容

  1. Hello, Template!

嵌入子模板

为了实现代码的重用,DotLiquid的模板还可以嵌入其他子模板,嵌入需要使用include标签。

以下例子会显示Hello, Include!

  1. public ActionResult HelloInclude()
  2. {
  3. return DotliquidView();
  4. }

文件~/DotliquidViews/Home/HelloInclude.html的内容

  1. Hello, {% include "~/DotliquidViews/Home/HelloIncludeContents.html" %}!

文件~/DotliquidViews/Home/HelloIncludeContents.html的内容

  1. Include

继承父模板

除了嵌入子模版,还能实现布局(Layout)方式的继承父模板,继承需要使用extends和block标签。

以下例子会返回Html<div class="layout"><h1>Here is title</h1><p>Here is body</p></div>

  1. public ActionResult HelloExtends()
  2. {
  3. return DotliquidView();
  4. }

文件~/DotliquidViews/Home/HelloExtendsLayout.html的内容

  1. <div class="layout">
  2. <h1>
  3. {% block title %}
  4. Default title
  5. {% endblock %}
  6. </h1>
  7. <p>
  8. {% block body %}
  9. Default body
  10. {% endblock %}
  11. </p>
  12. </div>

文件~/DotliquidViews/Home/HelloExtends.html的内容

  1. {% extends "~/DotliquidViews/Home/HelloExtendLayout.html" %}
  2. {% block title %}
  3. Here is title
  4. {% endblock %}
  5. {% block body %}
  6. Here is body
  7. {% endblock %}

描画自定义对象

请先看以下的例子

  1. public class ExampleViewModel
  2. {
  3. public string Name { get; set; }
  4. public int Age { get; set; }
  5. }
  1. public ActionResult CustomObject()
  2. {
  3. var template = Template.Parse("Name: {{ model.Name }}, Age: {{ model.Age }}");
  4. var model = new ExampleViewModel() { Name = "john", Age = 35 };
  5. var result = template.Render(Hash.FromAnonymousObject(new { model }));
  6. return Content(result);
  7. }

你可能预料这个例子会显示Name: john, Age: 35,但实际运行时会给出以下错误

  1. Name: Liquid syntax error: Object 'Dotliquid.Example.Dotliquid.ExampleViewModel' is invalid because it is neither a built-in type nor implements ILiquidizable, Age: Liquid syntax error: Object 'Dotliquid.Example.Dotliquid.ExampleViewModel' is invalid because it is neither a built-in type nor implements ILiquidizable

这是因为DotLiquid为了安全性,默认不允许描画未经注册的对象,这样即使模板由前端使用者提供也不会导致信息泄露。

为了解决上面的错误,需要把ExampleViewModel注册为可描画的对象。

除了使用RegisterSafeType注册,你也可以让ExampleViewModel继承ILiquidizable,在部分场景下会更适合。

  1. public class MvcApplication : System.Web.HttpApplication
  2. {
  3. protected void Application_Start()
  4. {
  5. // 在原有的代码下添加
  6. Template.RegisterSafeType(typeof(ExampleViewModel), Hash.FromAnonymousObject);
  7. }
  8. }

写在最后

DotLiquid是一个灵活性很高并且依赖很少的模板引擎,虽然没有Razor流行,但大量的单元测试保证它可以经得起实际的使用。

目前使用了DotLiquid的项目有

目前DotLiquid准备升级2.0版本,作者正在召集PR,如果你有意向可以到DotLiquid的github看看。

DotLiquid模板引擎简介的更多相关文章

  1. JST(JavaScript Trimpath)前端模板引擎简介

    JST(JavaScript Trimpath)前端模板引擎简介及应用 今天在做某系统日志列表的时候用到了这个玩意儿.刚开始只是根据别人的例子照葫芦画瓢完成了日志列表及对应详情,晚上有空了才仔细去网上 ...

  2. Smarty 模板引擎简介

    前言 Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一.它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑 ...

  3. Thymeleaf 模板引擎简介

    目录 Thymeleaf 模板引擎 官方文档下载 Hello World 新建应用 后台控制器 前端页面 浏览器访问测试 Thymeleaf 模板引擎1.Thymeleaf 是 Web 和独立环境的现 ...

  4. thymeleaf模板引擎简介

    一:thymeleaf 学习笔记---http://www.blogjava.net/bjwulin/articles/395185.html thymeleaf是一个支持html原型的自然引擎,它在 ...

  5. Spring Boot 系列(五)web开发-Thymeleaf、FreeMarker模板引擎

    前面几篇介绍了返回json数据提供良好的RESTful api,下面我们介绍如何把处理完的数据渲染到页面上. Spring Boot 使用模板引擎 Spring Boot 推荐使用Thymeleaf. ...

  6. SpringBoot系列之集成jsp模板引擎

    目录 1.模板引擎简介 2.环境准备 4.源码原理简介 SpringBoot系列之集成jsp模板引擎 @ 1.模板引擎简介 引用百度百科的模板引擎解释: 模板引擎(这里特指用于Web开发的模板引擎)是 ...

  7. C#模板引擎 DotLiquid

    DotLiquid 是一个简单.快速和安全的模板引擎,移植自 Ruby 的 Liquid 标签. 示例模板: <p>{{ user.name }} has to do:</p> ...

  8. 一,Smarty模板技术/引擎——简介

    Smarty是一个使用PHP写出来的模板PHP模板引擎,它提供了逻辑与外在内容的分离,简单的讲,目的就是要使PHP程序员与美工分离,使用的程序员改变程序的逻辑内容不会影响到美工的页面设计,美工重新修改 ...

  9. Python模板引擎Jinja2使用简介

    原文链接 背景 最近在项目开发中,需要针对 Jenkins 项目进行配置,Jenkins 的 job 配置采用的是 xml,在维护配置模板的过程中就遇到了问题,因为逐步发现配置灵活性超出了字符串的范畴 ...

随机推荐

  1. Asp.Net Mvc 使用WebUploader 多图片上传

    来博客园有一个月了,哈哈.在这里学到了很多东西.今天也来试着分享一下学到的东西.希望能和大家做朋友共同进步. 最近由于项目需要上传多张图片,对于我这只菜鸟来说,以前上传图片都是直接拖得控件啊,而且还是 ...

  2. 再部署一个 instance 和 Local Network - 每天5分钟玩转 OpenStack(131)

    上一节部署了 cirros-vm1 到 first_local_net,今天我们将再部署 cirros-vm2 到同一网络,并创建 second_local_net. 连接第二个 instance 到 ...

  3. DBA成长路线

    从开发转为数据库管理,即人们称为DBA的已经有好几年,有了与当初不一样的体会.数据是企业的血液,数据是石油,数据是一切大数据.云计算的基础.作为DBA是数据的保卫者.管理者,是企业非常重要的角色.对于 ...

  4. spring applicationContext.xml和hibernate.cfg.xml设置

    applicationContext.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans ...

  5. Android SDK 与API版本对应关系

    Android SDK版本号 与 API Level 对应关系如下表: Code name Version API level   (no code name) 1.0 API level 1   ( ...

  6. 用Swagger生成接口文档

    Swagger简介 在系统设计的时候,各个应用之间往往是通过接口进行交互的.因此接口的定义在整个团队中就变得尤为重要.我们可以把接口的规范用接口描述语言进行描述,然后Swagger可以根据我们定义的接 ...

  7. Atitit.软件研发团队建设原理与概论 理论

    Atitit.软件研发团队建设原理与概论 理论 培训 团队文化建设(内刊,ppt,书籍,杂志等) 梯队建设 技术储备人才的问题 团队建设--小红花评比. 团队建设--文化墙.doc 户外拓展 1. 团 ...

  8. 打开程序总是会提示“Enter password to unlock your login keyring” ,如何成功关掉?

    p { margin-bottom: 0.1in; line-height: 120% } 一.一开始我是按照网友所说的 : rm -f ~/.gnome2/keyrings/login.keyrin ...

  9. 【QQ红包】手机发抢不到的口令红包

    这方法95%的人都抢不了 在QQ输入框输入一个表情,例如:阴险那个表情 将表情剪切到口令红包的口令里 这时候口令里的那个表情表情变成了符号 将符号删去一格,然后全选.复制 然后返回到QQ输入框粘贴 然 ...

  10. CentOS 7 上部署Mono 4 和Jexus 5.6

    概述 在这篇文章中我们将讨论如何在CentOS 7操作系统,安装 jexus. mono 和 配置 jexus,因此它将能够在这种环境中运行一个asp.net mvc 4 应用.这篇文章是描述如何在 ...