@Include()
)@Raw()
RazorEngine.Razor
已廢棄,請改用 Engine.Razor
Open source templating engine based on Microsoft's Razor parsing engine.javascript
Install-Package RazorEngine
Install-Package RazorEngine -Version 3.6.4
https://www.nuget.org/packages/RazorEngine/ - latest: RazorEngine 3.6.4, Friday, March 27 2015php
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.html
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.java
Installed into Net451Console via NuGet at 2016-07-31:github
------- 正在安裝...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
。web
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緩存
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 個文件,該目錄及其中的所有文件的名稱都是隨機的,例如:
單步執行完畢後 (Tony 理解爲應用程序域已終止並釋放),其它 5 個文件已自動移除,但 .dll 文件及該目錄會殘留。如下爲 4 次單步執行後的殘留:
官網提供了上述問題的解決方案,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;
}
}
}
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」中找到入口點。
。如下測試代碼整理自 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; }
}
}
如下測試代碼整理自 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
的值無關。如下測試代碼整理自 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; }
}
}
如下測試代碼整理自 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;
}
}
}
@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;
}
}
}
@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);
}
}
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
《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;
}
}
@Include()