目錄
- 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 RazorEngineInstall-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,@RenderSectionand@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.csusing 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.csusing 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 debuggingvar 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 typevar model1 = new { Name = "Matt" }; //anonymous typedynamic model2 = new ExpandoObject(); //dynamic typemodel2.Name = "Matt"; //dynamic typestring result0 = Engine.Razor.RunCompile(template, "key0", typeof(Person), model0); //statically typestring result1 = Engine.Razor.RunCompile(template, "key1", null, model1); //anonymous typestring 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#endregionnamespace 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 BOMsw.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 {//獲取模板Htmlstring 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 的程序集生成方式
