介绍
Razor是一个用于将基于.NET的代码嵌入到网页中的标记语法。Razor语法由 Razor 标记、C#代码 和 HTML 组成。.
目的
借助组件使用 Razor 语法构建动态模板。
实现效果:提前定义一个HTML模板,来动态填充内容并得到结果。
操作
模板准备
<div>
<table border="1" style="border:1px solid black;text-align:center" cellpadding="1" cellspacing="1">
<tr>
<th colspan="2">@Model.UserName</th>
</tr>
<tr>
<td>科目</td>
<td>成绩</td>
</tr>
@foreach (var item in Model.SubjectList)
{
<tr>
<td>@item.SubjectName</td>
<td>@item.Grade</td>
</tr>
}
</table>
</div>
需要右键设置始终复制
涉及到的UserGradeDto类如下
namespace RazorEngineConsoleApp.Models
{
public class UserGradeDto
{
public string UserName { get; set; } = null!;
/// <summary>
/// 科目成绩集合
/// </summary>
public IEnumerable<SubjectGradeDto> SubjectList { get; set; } = null!;
public static UserGradeDto GetInfo()
{
return new UserGradeDto
{
UserName = "张三",
SubjectList = new List<SubjectGradeDto>
{
new SubjectGradeDto
{
SubjectName = "语文",
Grade = 90
},
new SubjectGradeDto
{
SubjectName = "数学",
Grade = 80
},
new SubjectGradeDto
{
SubjectName = "英语",
Grade = 70
}
}
};
}
}
public class SubjectGradeDto
{
/// <summary>
/// 科目名字
/// </summary>
public string SubjectName { get; set; } = null!;
/// <summary>
/// 成绩
/// </summary>
public int Grade { get; set; }
}
}
RazorEngine
介绍
RazorEngine 是基于 Microsoft 的 Razor 解析引擎构建的模板引擎,允许您使用 Razor 语法构建动态模板。
组件:
RazorEngine
支持NetFramework4.0和4.5,最新更新时间2017.06.16
仓库地址:https://github.com/Antaris/RazorEngine
RazorEngine.NetCore
支持.NetCore3.1、.NetSandard2.1,最新更新时间2020.06.19
仓库地址:https://github.com/fouadmess/RazorEngine
这两个包都已经不再更新,但是该项目正在寻求新的维护者,感兴趣的可以去研究下源码。
原理
.Net在编译的时候会把.cshtml文件生成一个动态程序集,每次调用,就会每次生成一个不重复的动态程序集,通过设置模板key来实现一次编译,下次会使用缓存,不会生成新的动态程序集。
如果cshtml文件发生了修改,那么还调用缓存的话,那么就不合适了,所以可以将模板key设置为动态的。
-
根据文件名+修改时间 -
文件的MD5值作为模板key
Razor模板引擎:https://www.cnblogs.com/green-jcx/p/5786669.html
操作
示例环境:VS2022、.NetCore3.1、控制台程序
引用组件
<ItemGroup>
<PackageReference Include="RazorEngine.NetCore" Version="3.1.0" />
</ItemGroup>
模板通过强类型方式填充
配置生成的代码
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "usergrade1.cshtml");
if (!File.Exists(filePath))
{
Console.WriteLine("模板文件不存在");
return;
}
//打开并且读取模板
string template = File.ReadAllText(filePath);
//一次编译多次使用
{
//modelType为null
//添加模板
Engine.Razor.AddTemplate("usergrade1", template);
//编译模板
Engine.Razor.Compile("usergrade1", modelType: null);
//运行模板
string str = Engine.Razor.Run("usergrade1", modelType: null, UserGradeDto.GetInfo());
Console.WriteLine(str);
//modelType不为null
////添加模板
//Engine.Razor.AddTemplate("usergrade1", template);
////编译模板
//Engine.Razor.Compile("usergrade1", typeof(UserGradeDto));
////运行模板
//string str = Engine.Razor.Run("usergrade1", typeof(UserGradeDto), UserGradeDto.GetInfo());
//Console.WriteLine(str);
}
//一次编译一次使用
{
//var str = Engine.Razor.RunCompile(template, "usergrade1", typeof(UserGradeDto), UserGradeDto.GetInfo());
}
生成结果
<div>
<table border="1" style="border:1px solid black;text-align:center" cellpadding="1" cellspacing="1">
<tr>
<th colspan="2">张三</th>
</tr>
<tr>
<td>科目</td>
<td>成绩</td>
</tr>
<tr>
<td>语文</td>
<td>90</td>
</tr>
<tr>
<td>数学</td>
<td>80</td>
</tr>
<tr>
<td>英语</td>
<td>70</td>
</tr>
</table>
</div>
模板通过dynamic填充
配置生成的代码
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "usergrade2.cshtml");
if (!File.Exists(filePath))
{
Console.WriteLine("模板文件不存在");
return;
}
//打开并且读取模板
string template = File.ReadAllText(filePath);
//dynamic方式
var result = Engine.Razor.RunCompile(template, "templateKey", null, new { UserName = "李思", SubjectList = new List<SubjectGradeDto> { new SubjectGradeDto { SubjectName = "语文", Grade = 90 } } });
Console.WriteLine(result);
这里的SubjectGradeDto内容就是上面UserGradeDto的内容
生成结果和上面示例结果一致,不再张贴。
RazorLight
介绍
在ASP.NET MVC 之外的 .NET Core使用 Razor 从字符串/文件/嵌入式资源构建模板。
官网文档:https://github.com/toddams/RazorLight#quickstart
组件:
RazorLight
支持.NetStandard2.0、.NetCore3.1、.Net5、.Net6,最新更新时间2022.03.19
仓库地址:https://github.com/toddams/RazorLight
操作
示例环境:VS2022、.Net6、控制台程序。(也可以通过依赖注入方式进行操作)
引用组件
<PackageReference Include="RazorLight" Version="2.0.0" />
为了防止后续出现错误:Can't load metadata reference from the entry assembly,可以提前修改csproj文件,增加如下配置
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<!--razor配置-->
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
具体填充模板操作
public async Task FillTemplateAsync()
{
//动态编译razor
var engine = new RazorLightEngineBuilder()
.UseEmbeddedResourcesProject(typeof(Program))//必须有一个模板的类型
.SetOperatingAssembly(typeof(Program).Assembly)
.UseMemoryCachingProvider()
.DisableEncoding()//禁用编码,否则会把中文字符串编码成Unicode
.Build();
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "View", "usergrade1.cshtml");
if (!File.Exists(filePath))
{
Console.WriteLine("模板文件不存在");
return;
}
//打开并且读取模板
string template = File.ReadAllText(filePath);
//运行
string result = await engine.CompileRenderStringAsync("templateKey", template, UserGradeDto.GetInfo());
Console.WriteLine(result);
}
输出结果
<div>
<table border="1" style="border:1px solid black;text-align:center" cellpadding="1" cellspacing="1">
<tr>
<th colspan="2">张三</th>
</tr>
<tr>
<td>科目</td>
<td>成绩</td>
</tr>
<tr>
<td>语文</td>
<td>90</td>
</tr>
<tr>
<td>数学</td>
<td>80</td>
</tr>
<tr>
<td>英语</td>
<td>70</td>
</tr>
</table>
</div>
其他的更多的操作可以看官网,我目前就用到这些。
总结
通过该Razor可以实现动态生成代码等操作,可玩性还挺高。
本文示例代码:https://github.com/azrng/dotnet-sample/tree/main/src/RazorSample
资料
Razor语法参考:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/razor?view=aspnetcore-6.0