Razor - 模板引擎 / 代码生成 - RazorEngine
目录
- Brief
- Authors
- Official Website
- RazorEngine 的原理 - 官方解释
- 安装记录
- Supported Syntax (默认实现支持的语法)
- 测试记录 - can't cleanup temp files
- 测试记录 - Quick Start
- 测试记录 - Configuration
- 测试记录 - 对比 3 种 Type 的 model 的语法
- 测试记录 - 扩展模板语法
- 测试记录 - Layout
- 测试记录 - Partial (
@Include()
) - Encoding Values -
@Raw()
RazorEngine.Razor
已废弃,请改用Engine.Razor
- 缓存
- 作者说: 无法稍毁缓存
- 某网文代码
- 安全 - 只可能内部使用、不能让用户定义模板
- Resource - Hello World
- Resource - Advanced
- base or advanced
Brief
Open source templating engine based on Microsoft's Razor parsing engine.
Authors
- Matthew Abbott
- Ben Dornis
- Matthias Dittrich
Official Website
GitHub
- http://github.com/Antaris/RazorEngine
- http://github.com/Antaris/RazorEngine#quickstart - quick start
- http://antaris.github.io/RazorEngine - latest documentation available (官方文档 - 截至 2016-07-24 能找到的最好的文档)
- http://antaris.github.io/RazorEngine/ReferenceResolver.html - Reference Resolver - 截至 2016-08-20 暂未遇到应用场景,留待有需要时再深入研究。
- http://antaris.github.io/RazorEngine/Isolation.html - RazorEngine Isolation API - 截至 2016-08-20 暂未遇到应用场景,留待有需要时再深入研究。
- Resolving and Caching Templates
- http://antaris.github.io/RazorEngine/TemplateManager.html - ITemplateManager and ICachingProvider - 截至 2016-08-21 暂未遇到应用场景,留待有需要时再深入研究。
- http://antaris.github.io/RazorEngine/Upgrading.html - Upgrading RazorEngine
- http://antaris.github.io/RazorEngine/IntellisenseAndResharper.html - Intellisense and ReSharper
- http://antaris.github.io/RazorEngine/references/index.html - references
CodePlex - obsolete
NuGet
Install-Package RazorEngine
Install-Package RazorEngine -Version 3.6.4
https://www.nuget.org/packages/RazorEngine/ - latest: RazorEngine 3.6.4, Friday, March 27 2015
Stack Overflow
- http://stackoverflow.com/search?q=RazorEngine - 1,100 results at 2016-08-14
- http://stackoverflow.com/questions/tagged/razorengine
RazorEngine 的原理 - 官方解释
There is often a confusion about where Razor sits in this set of technologies. Essentially Razor is the parsing framework that does the work to take your text template and convert it into a compilable class. In terms of MVC and WebPages, they both utilise this parsing engine to convert text templates (view/page files) into executable classes (views/pages). Often we are asked questions such as "Where is @Html, @Url", etc. These are not features provided by Razor itself, but implementation details of the MVC and WebPages frameworks.
RazorEngine is another consumer framework of the Razor parser. We wrap up the instantiation of the Razor parser and provide a common framework for using runtime template processing.
安装记录
Installed into Net451Console via NuGet at 2016-07-31:
------- 正在安装...RazorEngine 3.9.0 -------
正在尝试解析依赖项“Microsoft.AspNet.Razor (≥ 3.0.0)”。
正在安装“Microsoft.AspNet.Razor 3.0.0”。
已将文件“System.Web.Razor.dll”添加到文件夹“Microsoft.AspNet.Razor.3.0.0\lib\net45”。
已将文件“System.Web.Razor.xml”添加到文件夹“Microsoft.AspNet.Razor.3.0.0\lib\net45”。
已将文件“Microsoft.AspNet.Razor.3.0.0.nuspec”添加到文件夹“Microsoft.AspNet.Razor.3.0.0”。
已将文件“Microsoft.AspNet.Razor.3.0.0.nupkg”添加到文件夹“Microsoft.AspNet.Razor.3.0.0”。
已成功安装“Microsoft.AspNet.Razor 3.0.0”。
正在安装“RazorEngine 3.9.0”。
已将文件“RazorEngine.dll”添加到文件夹“RazorEngine.3.9.0\lib\net40”。
已将文件“RazorEngine.xml”添加到文件夹“RazorEngine.3.9.0\lib\net40”。
已将文件“RazorEngine.dll”添加到文件夹“RazorEngine.3.9.0\lib\net45”。
已将文件“RazorEngine.xml”添加到文件夹“RazorEngine.3.9.0\lib\net45”。
已将文件“LICENSE.md”添加到文件夹“RazorEngine.3.9.0”。
已将文件“RazorEngine.3.9.0.nuspec”添加到文件夹“RazorEngine.3.9.0”。
已将文件“RazorEngine.3.9.0.nupkg”添加到文件夹“RazorEngine.3.9.0”。
已成功安装“RazorEngine 3.9.0”。
正在将“Microsoft.AspNet.Razor 3.0.0”添加到 Console。
已将引用“System.Web.Razor”添加到项目“Console”
已添加文件“packages.config”。
已将文件“packages.config”添加到项目“Console”
已成功将“Microsoft.AspNet.Razor 3.0.0”添加到 Console。
正在将“RazorEngine 3.9.0”添加到 Console。
已将引用“RazorEngine”添加到项目“Console”
已添加文件“packages.config”。
已成功将“RazorEngine 3.9.0”添加到 Console。
==============================
总结: 共安装了两个 DLL: System.Web.Razor.dll
、RazorEngine.dll
。
Supported Syntax (默认实现支持的语法)
You can access several things when you use the default
TemplateBase<>
implementation:
*@using Custom.Namespace
(see also the quick intro and assembly resolvers for custom references)
*@model ModelType
*@inherits HtmlSupportTemplateBase<ModelType>
(see below)
* Set a layout (and@RenderBody()
within the layout template):@{ Layout = "layout.cshtml"; }
*@Include("templateName", model = null, modelType = null)
to include another template.
* Accessing the ViewBag:<h1>@ViewBag.Title</h1>
* Sections (@DefineSection
,@RenderSection
and@IsSectionDefined
)-- http://antaris.github.io/RazorEngine/TemplateBasics.html#Supported-syntax
测试记录 - can't cleanup temp files
2015-10-19 Tony 在 .NET4.51 Console Application 中单步执行以下代码时弹出命令行窗口显示以下信息:
代码:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
// using RazorEngine.Templating; // Dont forget to include this.
string template = "Hello @Model.Name, welcome to RazorEngine!";
var result = Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
}
}
}
信息:
RazorEngine: We can't cleanup temp files if you use RazorEngine on the default Appdomain.
Create a new AppDomain and use RazorEngine from there.
Read the quickstart or https://github.com/Antaris/RazorEngine/issues/244 for details!
You can ignore this and all following 'Please clean ... manually' messages if you are using DisableTempFileLocking, which is not recommended.
Please clean 'C:\Users\User0\AppData\Local\Temp\RazorEngine_********.***' manually!
每次单步执行 RazorEngine.Engine.Razor.RunCompile()
后,都会生成 1 个目录及该目录中的 6 个文件,该目录及其中的全部文件的名称都是随机的,例如:
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\CompiledRazorTemplates.Dynamic.RazorEngine_290440367cc04e8c9d06a99a7a805d08.dll"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\filbbops.0.cs"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\filbbops.cmdline"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\filbbops.err"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\filbbops.out"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\filbbops.tmp"
单步执行完毕后 (Tony 理解为应用程序域已终止并释放),其它 5 个文件已自动移除,但 .dll 文件及该目录会残留。以下为 4 次单步执行后的残留:
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_bmze52rx.ovb\CompiledRazorTemplates.Dynamic.RazorEngine_a291215db8fd497cae3e4a2bfcabe7b2.dll"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_tkidehx4.qay\CompiledRazorTemplates.Dynamic.RazorEngine_bd299256d8b94f64ba943c5a09014ed6.dll"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_a1anyws2.vvo\CompiledRazorTemplates.Dynamic.RazorEngine_f890b330f6104de19631e25ea528a6e8.dll"
- "C:\Users\User0\AppData\Local\Temp\RazorEngine_pv3sxecv.dyv\CompiledRazorTemplates.Dynamic.RazorEngine_290440367cc04e8c9d06a99a7a805d08.dll"
官网提供了上述问题的解决方案,2017-03-15 编写以下代码对该方案进行了测试,结论: 该方案在控制台程序中有效:
//Program.cs
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
string template = "Hello @Model.Name, welcome to RazorEngine!";
var result = Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
//执行上一行后创建了 "C:\Users\User0\AppData\Local\Temp\RazorEngine_tbr5ujmj.fju" 目录及其中的 6 个文件。
var isTrue = result == "Hello World, welcome to RazorEngine!";
#endregion test code.
return 123;
}
//退出 Main() 后 "C:\Users\User0\AppData\Local\Temp\RazorEngine_tbr5ujmj.fju" 目录被删除。
}
}
//NewDomain.cs
using System;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
namespace Net451Console
{
class NewDomain
{
/// <summary>
/// 如果 应用程序域 非 进程的默认应用程序域,则 不作任何处理、直接返回 false;
/// 如果 应用程序域 是 进程的默认应用程序域,则 创建新的应用程序域、并在该域中执行当前程序集、接着卸载该域、并返回 true。
/// </summary>
public static bool Switch()
{
bool isDefaultAppDomain = AppDomain.CurrentDomain.IsDefaultAppDomain();
if(!isDefaultAppDomain) {
return false;
}
// RazorEngine cannot clean up from the default appdomain...
Console.WriteLine("Switching to second AppDomain, for RazorEngine...");
//2017-03-15 已测试证明以下两行代码无用:
//AppDomainSetup adSetup = new AppDomainSetup();
//adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
//测试记录: 至此 adSetup.ApplicationBase 的值为 "D:\Test\Net451Console\branches\RazorEngine\Net451Console\bin\Debug\"。
// You only need to add strongnames when your appdomain is not a full trust environment.
AppDomain domain = AppDomain.CreateDomain(
"MyMainDomain",
null,
AppDomain.CurrentDomain.SetupInformation,
new PermissionSet(PermissionState.Unrestricted),
new StrongName[0]
);
string location = Assembly.GetExecutingAssembly().Location;
//测试记录: 至此 location 的值为 "D:\Test\Net451Console\branches\RazorEngine\Net451Console\bin\Debug\Net451Console.exe"。
int exitCode = domain.ExecuteAssembly(location);
//执行上一行的 domain.ExecuteAssembly() 导致重新执行 Main(),届时 isDefaultAppDomain 为 false,将跳过本方法主体转而执行 Mian() 中的剩余代码,Main() 的返回值将成为上一行的返回值并赋给 exitCode,接着执行下 2 行代码,最后退出本方法。
// Note that you need to Unload the domain to trigger cleanup.
// RazorEngine will cleanup.
AppDomain.Unload(domain);
//执行上一行后 "C:\Users\User0\AppData\Local\Temp\RazorEngine_tbr5ujmj.fju" 目录中的 6 个文件仅剩下 1 个 .dll 文件。
return true;
}
}
}
测试记录 - 以上方案仅在控制台程序中有效、在 ASP.NET MVC 中无效
- 在 ASP.NET MVC 中
AppDomain.CurrentDomain.IsDefaultAppDomain()
总是返回false
。 - 执行
Assembly.GetExecutingAssembly().Location
返回C:\Users\User0\AppData\Local\Temp\Temporary ASP.NET Files\root\b54c3416\14425600\assembly\dl3\57a31749\d172b5e9_d29fd201\Net451MvcNoAuth.dll
,接着执行下一行domain.ExecuteAssembly(location)
报错异常详细信息: System.MissingMethodException: 未在程序集“Net451MvcNoAuth, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中找到入口点。
。
测试记录 - Quick Start
以下测试代码整理自 http://antaris.github.io/RazorEngine/index.html#Quickstart:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
//All you need to do is use the static Engine class (the Engine.Razor instance) in the 'RazorEngine' namespace:
string template = "Hello @Model.Name, welcome to RazorEngine!";
string key = "templateKey";
var result0 = Engine.Razor.RunCompile(template, key, null, new { Name = "World" });
//The "templateKey" must be unique and after running the above example you can re-run the cached template with this key.
var result1 = Engine.Razor.Run(key, null, new { Name = "Max" });
//The null parameter is the modelType and null in this case means we use dynamic as the type of the model. You can use a static model as well by providing a type object.
var result2 = Engine.Razor.RunCompile(key, typeof(Person), new Person { Name = "Max" });
//Note that we now re-compile the model with a different type. When you do not run the same template a lot of times (like several 1000 times), compiling uses the most time. So the benefit you get from a static type will most likely not compensate the additional compile time. Therefore you should either stick to one type for a template (best of both worlds) or just use (the slower) dynamic (null). You can specify the modelType of a template with the @model directive. When you do this the modelType parameter is ignored, but you should use the same type instance (or null) on every call to prevent unnecessary re-compilations because of type mismatches in the caching layer.
#endregion test code.
return 123;
}
}
public class Person
{
public string Name { get; set; }
}
}
测试记录 - Configuration
以下测试代码整理自 http://antaris.github.io/RazorEngine/index.html#Configuration:
using RazorEngine;
using RazorEngine.Configuration;
using RazorEngine.Templating;
using RazorEngine.Text;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
//You can configure RazorEngine with the TemplateServiceConfiguration class.
var config = new TemplateServiceConfiguration();
// ... configure your instance
//General Configuration
//By default RazorEngine is configured to encode using Html. This supports the majority of users but with some configuration changes you can also set it to encode using Raw format which is better suited for templates that generate things like javascript, php, C# and others.
config.Language = Language.CSharp; // C# as template language.
config.EncodedStringFactory = new RawStringFactory(); // Raw string encoding.
//config.EncodedStringFactory = new HtmlEncodedStringFactory(); // Html encoding.
//One thing you might want to enable is the debugging feature:
config.Debug = true;
IRazorEngineService service = RazorEngineService.Create(config);
//If you want to use the static Engine class with this new configuration:
Engine.Razor = service;
//When Debug is true you can straight up debug into the generated code. RazorEngine also supports debugging directly into the template files (normally .cshtml files). As as you might see in the above code there is no file to debug into. To provide RazorEngine with the necessary information you need to tell where the file can be found:
string template = "Hello @Model.Name, welcome to RazorEngine!";
string templateFile = "d:/mytemplate.cshtml";
// Provide a non-null file to improve debugging
var loadedTemplateSource = new LoadedTemplateSource(template, templateFile);
var result = Engine.Razor.RunCompile(loadedTemplateSource, "templateKey", null, new { Name = "World" });
//This time when debugging the template you will jump right into the template file.
#endregion test code.
return 123;
}
}
}
上述代码中的 d:/mytemplate.cshtml
的测试记录:
- 该文件中的断点有效。
- 该文件的内容与
template
的值无关。 - 该文件的内容可为任意字符 (包括空文件)。
- 该文件不能放在 Windows10 的 C 分区,否则会因为访问权限而报错。
测试记录 - 对比 3 种 Type 的 model 的语法
以下测试代码整理自 http://antaris.github.io/RazorEngine/TemplateBasics.html:
using RazorEngine;
using RazorEngine.Templating;
using System.Dynamic;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
string template = "<div>Hello @Model.Name</div>";
var model0 = new Person { Name = "Matt" }; //statically type
var model1 = new { Name = "Matt" }; //anonymous type
dynamic model2 = new ExpandoObject(); //dynamic type
model2.Name = "Matt"; //dynamic type
string result0 = Engine.Razor.RunCompile(template, "key0", typeof(Person), model0); //statically type
string result1 = Engine.Razor.RunCompile(template, "key1", null, model1); //anonymous type
string result2 = Engine.Razor.RunCompile(template, "key2", null, (object)model2); //dynamic type
//执行至此 result0-2 均为 "<div>Hello Matt</div>"。
#endregion test code.
return 123;
}
}
public class Person
{
public string Name { get; set; }
}
}
测试记录 - 扩展模板语法
以下测试代码整理自 http://antaris.github.io/RazorEngine/TemplateBasics.html#Extending-the-template-Syntax:
using RazorEngine.Configuration;
using RazorEngine.Templating;
using RazorEngine.Text;
using System;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
var config = new TemplateServiceConfiguration();
// You can use the @inherits directive instead (this is the fallback if no @inherits is found).
config.BaseTemplateType = typeof(HtmlSupportTemplateBase<>);
using(var service = RazorEngineService.Create(config)) {
string template0 = "@Model.Data";
string template1 = "@Html.Raw(Model.Data)";
string data = "My raw double quotes appears here \"hello!\"";
var model = new { Data = data };
string result0 = service.RunCompile(template0, "htmlRawTemplate0", null, model);
string result1 = service.RunCompile(template1, "htmlRawTemplate1", null, model);
if(result0 == "My raw double quotes appears here "hello!"") {
Console.WriteLine("* 默认行为: 引号被 HTML 实体编码。");
}
if(result1 == data) {
Console.WriteLine("* @Html.Raw() 原样输出。");
}
}
#endregion test code.
return 123;
}
}
public class MyHtmlHelper
{
public IEncodedString Raw(string rawString)
{
return new RawString(rawString);
}
}
public abstract class HtmlSupportTemplateBase<T> : TemplateBase<T>
{
//public MyClassImplementingTemplateBase()
public HtmlSupportTemplateBase()
{
Html = new MyHtmlHelper();
}
public MyHtmlHelper Html { get; set; }
}
}
测试记录 - Layout
以下测试代码整理自 http://antaris.github.io/RazorEngine/LayoutAndPartial.html#Layout-template:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
IRazorEngineService service = Engine.Razor;
service.AddTemplate("Layout0", @"<html>@RenderBody()</html>");
service.AddTemplate("Layout1", @"<body>@RenderBody()</body>@{ Layout = ""Layout0""; }");
service.AddTemplate("Layout2", @"<div> @RenderBody()</div> @{ Layout = ""Layout1""; }");
service.AddTemplate("templet", @"<h1> content in h1</h1> @{ Layout = ""Layout2""; }");
service.Compile("templet");
string result = service.Run("templet");
bool isTrue = result == "<html><body><div> <h1> content in h1</h1> </div> </body></html>";
#endregion test code.
return 123;
}
}
}
测试记录 - Partial (@Include()
)
以下测试代码整理自 http://antaris.github.io/RazorEngine/LayoutAndPartial.html#Partial-templates:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
var service = Engine.Razor;
service.AddTemplate("part", @"my template");
// If you leave the second and third parameters out the current model will be used.
// If you leave the third we assume the template can be used for multiple types and use "dynamic".
// If the second parameter is null (which is default) the third parameter is ignored.
// To workaround in the case you want to specify type "dynamic" without specifying a model use Include("p", new object(), null)
service.AddTemplate("template", @"<h1>@Include(""part"", @Model.SubModel, typeof(Net451Console.SubModel))</h1>");
service.Compile("template", typeof(MyModel));
service.Compile("part", typeof(SubModel));
var result = service.Run(
"template",
typeof(MyModel),
new MyModel {
ModelProperty = "model",
SubModel = new SubModel { SubModelProperty = "submodel" }
}
);
bool isTrue = result == "<h1>my template</h1>";
#endregion test code.
return 123;
}
}
public class SubModel
{
public string SubModelProperty { get; set; }
}
public class MyModel
{
public string ModelProperty { get; set; }
public SubModel SubModel { get; set; }
}
}
测试发现很多参数都可省略:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
var service = Engine.Razor;
service.AddTemplate("part", @"Text in the part.");
service.AddTemplate("template", @"<h1>@Include(""part"")</h1>");
service.Compile("template");
service.Compile("part");
var result = service.Run("template");
bool isTrue = result == "<h1>Text in the part.</h1>";
#endregion test code.
return 123;
}
}
}
Encoding Values - @Raw()
以下测试代码整理自 http://antaris.github.io/RazorEngine/Encoding.html:
using RazorEngine;
using RazorEngine.Templating;
namespace Net451Console
{
class Program
{
//static void Main(string[] args)
static int Main(string[] args)
{
bool isDefaultAppDomain = NewDomain.Switch();
if(isDefaultAppDomain) {
return 0;
}
#region test code:
//By default RazorEngine is configured to encode as Html. This sometimes this presents problems were certain characters are encoded as Html but what you want is to output them as-is. To output something in raw format use the @Raw() built-in method as shown in the following example:
string template0 = "@Model.Data";
string template1 = "@Raw(Model.Data)";
var model = new { Data = "My raw double quotes appears here \"hello!\"" };
string result0 = Engine.Razor.RunCompile(template0, "templateKey0", null, model);
string result1 = Engine.Razor.RunCompile(template1, "templateKey1", null, model);
bool isTrue0 = result0 == @"My raw double quotes appears here "hello!"";
bool isTrue1 = result1 == @"My raw double quotes appears here ""hello!""";
#endregion test code.
return 123;
}
}
}
测试记录 - 不支持 @Html.Raw()
执行 string test = Engine.Razor.RunCompile(@"@Html.Raw(""asdf"")", "key", null, string.Empty);
时抛出异常 "当前上下文中不存在名称“Html”"。
RazorEngine.Razor
已废弃,请改用 Engine.Razor
#region 程序集 RazorEngine.dll, v3.9.0.0
// D:\Test\Net451Console\branches\RazorEngine\packages\RazorEngine.3.9.0\lib\net45\RazorEngine.dll
#endregion
namespace RazorEngine
{
[Obsolete("Please use the Engine.Razor instance instead.")]
public static class Razor {
public static void Compile(string razorTemplate, string name);
...
public static ITemplate CreateTemplate(string razorTemplate);
...
public static ITemplate GetTemplate(string razorTemplate, string name);
...
public static string Parse(string razorTemplate);
...
public static ITemplate Resolve(string name);
...
public static string Run(string name);
...
public static void SetTemplateService(ITemplateService service);
}
}
缓存
- How are templates in RazorEngine cached?
- Antaris RazorEngine How to Recompile a template using the same Key?
- RazorEngine Memory Usage
- RazorEngine IsolatedTemplateService is not preventing growth of number of loaded assemblies
- Use external cache provider for RazorEngine
- Memcached Caching Provider and Serialization Issue #278
作者说: 无法稍毁缓存
When you change and recompile templates you have a memory leak, because you cannot unload loaded assemblies (which RazorEngine compiles and loads for you in the background).
The only way to really free the memory is to reload the AppDomain or restart the process.
-- http://stackoverflow.com/questions/14369614/razorengine-un-cache-compiled-templates
- RazorEngine un-cache compiled templates
- http://github.com/Antaris/RazorEngine/issues/232#issuecomment-128802285
- Essential Templating - is a set of libraries to render templated objects (like web pages or emails).
某网文代码
《ASP.NET MVC 解析模板生成静态页一 (RazorEngine)》 全文共两部分: 1. 基本的单数据模型模板解析; 2. 面向接口的多数据模型模板解析。该网文仅涉及到 RazorEngine 最基础的 API,未展示 Hello World 之外的功能。以下为第一部分的原始代码 (未改动、仅格式化)。第二部分核心代码与第一部分完全相同,仅增加了 TemplateView 模型解析类中间件、Repository、泛型、面向接口、Spring 依赖注入、反射赋值,所有这些增加的部分都是面向对象与设计模式的半桶水套路,无作用无意义徒增坏味道,跳过。
public class Articles
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public string Author { get; set; }
public DateTime CreateDate { get; set; }
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>@Model.Title</title>
</head>
<body>
<h1>@Model.Title</h1>
<p>作者:@Model.Author - 发布时间:@Model.CreateDate</p>
<p>@Raw(Model.Content)</p>
</body>
</html>
/// <summary>
/// 获取页面的Html代码
/// </summary>
/// <param name="url">模板页面路径</param>
/// <param name="encoding">页面编码</param>
public string GetHtml(string url, System.Text.Encoding encoding)
{
byte[] buf = new WebClient().DownloadData(url);
if(encoding != null){
return encoding.GetString(buf);
}
string html = System.Text.Encoding.UTF8.GetString(buf);
encoding = GetEncoding(html);
if(encoding == null || encoding == System.Text.Encoding.UTF8){
return html;
}
return encoding.GetString(buf);
}
/// <summary>
/// 获取页面的编码
/// </summary>
/// <param name="html">Html源码</param>
public System.Text.Encoding GetEncoding(string html)
{
string pattern = @"(?i)/bcharset=(?<charset>[-a-zA-Z_0-9]+)";
string charset = Regex.Match(html, pattern).Groups["charset"].Value;
try{
return System.Text.Encoding.GetEncoding(charset);
}
catch(ArgumentException){
return null;
}
}
/// <summary>
/// 创建静态文件
/// </summary>
/// <param name="result">Html代码</param>
/// <param name="createpath">生成路径</param>
public bool CreateFileHtmlByTemp(string result, string createpath)
{
if(!string.IsNullOrEmpty(result)) {
if(string.IsNullOrEmpty(createpath)) {
createpath = "/default.html";
}
string filepath = createpath.Substring(createpath.LastIndexOf(@"/"));
createpath = createpath.Substring(0, createpath.LastIndexOf(@"/"));
if (!Directory.Exists(createpath)) {
Directory.CreateDirectory(createpath);
}
createpath = createpath + filepath;
try {
FileStream fs2 = new FileStream(createpath, FileMode.Create);
StreamWriter sw = new StreamWriter(fs2, new System.Text.UTF8Encoding(false));//去除UTF-8 BOM
sw.Write(result);
sw.Close();
fs2.Close();
fs2.Dispose();
return true;
}
catch { return false; }
}
return false;
}
/// <summary>
/// 解析模板生成静态页
/// </summary>
/// <param name="temppath">模板地址</param>
/// <param name="path">静态页地址</param>
/// <param name="t">数据模型</param>
public bool CreateStaticPage(string temppath, string path, Articles t)
{
try {
//获取模板Html
string TemplateContent = GetHtml(temppath, System.Text.Encoding.UTF8);
//解析模板生成静态页Html代码
string result = Razor.Parse(TemplateContent, t);
//创建静态文件
return CreateFileHtmlByTemp(result, path);
}
catch (Exception e) {
throw e;
}
}
安全 - 只可能内部使用、不能让用户定义模板
- How dangerous is it to let users specify RazorEngine templates?
- RazorEngine for user templates - Security?
- ASP.NET Razor templates editable by users - remove @ for security reasons
Resource - Hello World
- 利用 RazorEngine 打造简单的泛用代码生成器 - 基于 ExpandoObject
- 利用 RazorEngine 更加直观的格式化字符串 - Note: 反射取值的 Regex.Replace() 有实用价值
Resource - Advanced
- 第四篇 基于 .NET 搭建热插拔式 Web 框架 (RazorEngine 实现)
- 用 Razor 語法寫範本 - RazorEngine 組件介紹
- 让 Windows2003 Server NET4.0 Frameworks 可以上使用 RazorEngine 程序集
- C# 模板引擎 RazorEngine 3.7 的简单使用
- RazorEngine 在非 MVC 下的使用,以及使用自定义模板
- .NET MVC Razor 也可以这样玩
- 在 ASP.NET WebAPI 中使用 Razor
- DIY RazorEngine 的程序集生成方式
- 抛弃 NVelocity,来玩玩 Razor - 文件嵌套、
@Include()
- Razor Engine,实现代码生成器的又一件利器
- Razor 模板引擎使用 - 缓存源码?
- C# & SQlite 代码生成器 - 非 HTML 模板示例
- Razor 模板引擎 - 缓存测试 & 封装
- 使用 Razor 模板构建应用注意的细节
base or advanced
- 用 Razor 語法寫範本 - RazorEngine 組件介紹
- 用 Razor 語法寫範本 - RazorEngine 組件介紹
- 让 Windows2003 Server NET4.0 Frameworks 可以上使用 RazorEngine 程序集
- RazorEngine - @Html.LabelFor OK, @Html.EditorFor "not implemented exception" on Execute()
- Dynamic CSS using Razor Engine
- Razor Templating Engine
- 代码生成就用 Razor 模板
- C# 模板引擎 RazorEngine 3.7 的扩展 — 引入外部文件
- C# 模板引擎 RazorEngine 3.7 的扩展 — 引用布局页
- 在非网页程序里使用 Razor 模板引擎
- ASP.NET MVC 解析模板生成静态页一 (RazorEngine) - 详见本文 "某网文代码" 小节
- DIY RazorEngine 的程序集生成方式
Razor - 模板引擎 / 代码生成 - RazorEngine的更多相关文章
- MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式
MVC的验证(模型注解和非侵入式脚本的结合使用) @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...
- Razor模板引擎 (RazorEngine)
Razor模板引擎不仅在ASP.NET MVC中内置了Razor模板引擎,还有一个开源的RazorEngine, 这样以来我们可以在非ASP.NET MVC项目中使用Razor引擎,甚至在控制台,Wi ...
- Razor模板引擎
Razor模板引擎 阅读目录 一.简介 二.非Mvc中使用Razor 三.总结 回到目录 一.简介 在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作:在以前我们一般常用的有Raz ...
- 脱离MVC使用Razor模板引擎
关于Razor模板引擎 1.简介 模板引擎:Razor.Nveocity.Vtemplate.Razor有VS自动提示.使用起来会方便一点. 但是Razor大多是在MVC下使用的. 那么如何在非MVC ...
- MVC Razor模板引擎输出HTML或者生产HTML文件
以前做CMS的时候都会根据模板来生成输出HTML或者生成HTML文件. 常用的引擎有VTemplate.NVelocity等等,这个我就布做介绍了. 这里我想说的是.当mvc出现Razor模板引擎的时 ...
- MVC小系列(二)【Razor 模板引擎】
Razor 模板引擎 Razor模板页:它使我们不用再使用master模板了 一 :@Url.Content:是可以加载CSS和JS等文件比如: <link href="@Url.Co ...
- [转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction
本文参考自下面文章整理 MVC Razor模板引擎 @RenderBody.@RenderPage.@RenderSection及Html.RenderPartial.Html.RenderActio ...
- .NET Core中使用Razor模板引擎
一.简介 在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作:在以前我们一般常用的有Razor.NVeocity.VTemplate.虽然所有的模板系统都具有一些共同特征,但 Ra ...
- Asp.net MVC Razor模板引擎技巧分享
Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...
随机推荐
- poj 3264(RMQ或者线段树)
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 42929 Accepted: 20184 ...
- python中global变量释疑
疑问 为什么main中不能写global x语句? 在函数中如何修改global变量? 在main中修改了global变量后,在子进程中为什么没有效果? 如何利用进程池的initializer参数(函 ...
- CSS 绝对居中方案
.Absolute-Center { margin: auto; position: absolute; top:;;;; }
- 596. Classes More Than 5 Students
There is a table courses with columns: student and class Please list out all classes which have more ...
- python版本管理(python环境隔离)
这将是一篇比较短的文章. 我发文向来注重文章质量,营养不够的宁可不发,但是我相信很多人需要这篇文章. 之所以要去搞清楚这个问题,是我在把 vscode 的 inspector 设置为 pipenv 生 ...
- LoadRunner 执行单句SQL语句
LoadRunner 执行单句SQL语句 Action() { int NumRows=0; int i=1; //建立数据库连接 lr_db_connect("StepName=Datab ...
- magento批量上传产品
Step1:表格仔细检查无误后,将准备好的图片上传至 media/import中.如果使用专用的图片服务器,把图片上传到服务器上,当然表格中的图片地址要做相应的修改. Step2:然后,登陆Magen ...
- 关于在windows下部署发布QT程序的总结
原文请看:http://www.cnblogs.com/javaexam2/archive/2011/05/18/2632916.html 关于在windows下部署发布QT程序的总结 2008-06 ...
- shell脚本学习(三)
shell echo命令 显示普通字符串: echo "I am cat_crazy.'" 注:这里的双引号可以省略 显示转义字符: 如果要输出引号,*号等需要转义才能输出,如下 ...
- PTA L2-023 图着色问题-前向星建图 团体程序设计天梯赛-练习集
L2-023 图着色问题 (25 分) 图着色问题是一个著名的NP完全问题.给定无向图,,问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色? 但本题并不是要你解 ...