在 .NET Core 中的 MVC 之外使用 Razor

2023-12-13

我想在我用 .NET Core 编写的 .NET 控制台应用程序中使用 Razor 作为模板引擎。

我遇到的独立 Razor 引擎(RazorEngine、RazorTemplates)都需要完整的 .NET。我正在寻找适用于 .NET Core 的解决方案。


下面是一个示例代码,仅依赖于 Razor(用于解析和 C# 代码生成)和 Roslyn(用于 C# 代码编译,但您也可以使用旧的 CodeDom)。

该代码段中没有 MVC,因此,没有 View,没有 .cshtml 文件,没有 Controller,只有 Razor 源解析和编译运行时执行。但仍然存在模型的概念。

您只需要添加以下 nuget 包:Microsoft.AspNetCore.Razor.Language(使用 v5.0.5 测试),Microsoft.AspNetCore.Razor.Runtime(使用 v2.2.0 测试)和Microsoft.CodeAnalysis.CSharp(使用 v3.9.0 测试)掘金。

此 C# 源代码与 .NET 5、NETCore 3.1(对于旧版本,请检查此答案的历史记录)、NETStandard 2 和 .NET Framework 兼容。要测试它,只需创建一个 .NET 框架或 .NET Core 控制台应用程序,粘贴它,添加 nuget,然后手动创建 hello.txt 文件(它必须位于可执行文件旁边)。

using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Hosting;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Extensions; // needed or not depends on .NET version
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace RazorTemplate
{
    class Program
    {
        static void Main(string[] args)
        {
            // points to the local path
            var fs = RazorProjectFileSystem.Create(".");

            // customize the default engine a little bit
            var engine = RazorProjectEngine.Create(RazorConfiguration.Default, fs, (builder) =>
            {
                // InheritsDirective.Register(builder); // in .NET core 3.1, compatibility has been broken (again), and this is not needed anymore...
                builder.SetNamespace("MyNamespace"); // define a namespace for the Template class
            });

            // get a razor-templated file. My "hello.txt" template file is defined like this:
            //
            // @inherits RazorTemplate.MyTemplate
            // Hello @Model.Name, welcome to Razor World!
            //

            var item = fs.GetItem("hello.txt", null);

            // parse and generate C# code
            var codeDocument = engine.Process(item);
            var cs = codeDocument.GetCSharpDocument();

            // outputs it on the console
            //Console.WriteLine(cs.GeneratedCode);

            // now, use roslyn, parse the C# code
            var tree = CSharpSyntaxTree.ParseText(cs.GeneratedCode);

            // define the dll
            const string dllName = "hello";
            var compilation = CSharpCompilation.Create(dllName, new[] { tree },
                new[]
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location), // include corlib
                    MetadataReference.CreateFromFile(typeof(RazorCompiledItemAttribute).Assembly.Location), // include Microsoft.AspNetCore.Razor.Runtime
                    MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location), // this file (that contains the MyTemplate base class)

                    // for some reason on .NET core, I need to add this... this is not needed with .NET framework
                    MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location), "System.Runtime.dll")),

                    // as found out by @Isantipov, for some other reason on .NET Core for Mac and Linux, we need to add this... this is not needed with .NET framework
                    MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location), "netstandard.dll"))
                },
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); // we want a dll


            // compile the dll
            string path = Path.Combine(Path.GetFullPath("."), dllName + ".dll");
            var result = compilation.Emit(path);
            if (!result.Success)
            {
                Console.WriteLine(string.Join(Environment.NewLine, result.Diagnostics));
                return;
            }

            // load the built dll
            Console.WriteLine(path);
            var asm = Assembly.LoadFile(path);

            // the generated type is defined in our custom namespace, as we asked. "Template" is the type name that razor uses by default.
            var template = (MyTemplate)Activator.CreateInstance(asm.GetType("MyNamespace.Template"));

            // run the code.
            // should display "Hello Killroy, welcome to Razor World!"
            template.ExecuteAsync().Wait();
        }
    }

    // the model class. this is 100% specific to your context
    public class MyModel
    {
        // this will map to @Model.Name
        public string Name => "Killroy";
    }

    // the sample base template class. It's not mandatory but I think it's much easier.
    public abstract class MyTemplate
    {
        // this will map to @Model (property name)
        public MyModel Model => new MyModel();

        public void WriteLiteral(string literal)
        {
            // replace that by a text writer for example
            Console.Write(literal);
        }

        public void Write(object obj)
        {
            // replace that by a text writer for example
            Console.Write(obj);
        }

        public async virtual Task ExecuteAsync()
        {
            await Task.Yield(); // whatever, we just need something that compiles...
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 .NET Core 中的 MVC 之外使用 Razor 的相关文章

  • 无法继承形状

    为什么我不能使用继承 a 的类Shapes class http msdn microsoft com en us library ms604615 28v vs 90 29 我需要延长Rectangle具有一些方法的类 但我想以与使用相同
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • 如何在 C# 中将 Json 转换为对象

    我想将 Json 转换为 C 中的对象 这里的 Json 是 值 e920ce0f e3f5 4c6f 8e3d d2fbc51990e4 如何使用 Object 问题看似愚蠢 但其实并不那么愚蠢 我没有简单的 Json 我有 IEnume
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • MVC 5 中具有 ASP.NET Identity 的 Autofac 不会验证 OWIN 管道中的安全标记

    我在 MVC 5 中设置了 AutoFac 来与 ASP NET Identity 一起使用 表面上一切似乎都工作正常 即用户可以创建帐户并登录 但后来我发现 当安全标记更改时 用户不会注销 通过在 AspNetUsers 表中进行暴力破解
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • wordexp 失败时我们需要调用 wordfree 吗?

    wordexp 失败时我们需要调用 wordfree 吗 在某些情况下 调用 wordfree 似乎会出现段错误 例如 当 wordfree 返回字符串为 foo bar 的错误代码时 这在手册页中并不清楚 我已经看到在某些错误情况下使用了
  • 如何防止 Blazor NavLink 组件的默认导航

    从 Blazor 3 1 Preview 2 开始 应该可以防止默认导航行为 https devblogs microsoft com aspnet asp net core updates in net core 3 1 preview
  • 如何在多线程应用程序中安全地填充数据并 Refresh() DataGridView?

    我的应用程序有一个 DataGridView 对象和一个 MousePos 类型的列表 MousePos 是一个自定义类 它保存鼠标 X Y 坐标 类型为 Point 和该位置的运行计数 我有一个线程 System Timers Timer
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • Unity3D - 将 UI 对象移动到屏幕中心,同时保持其父子关系

    我有一个 UI 图像 它的父级是 RectTransform 容器 该容器的父级是 UI 面板 而 UI 面板的父级是 Canvas 我希望能够将此 UI 图像移动到屏幕中心 即画布 同时保留父级层次结构 我的目标是将 UI 图像从中心动画
  • 如何在C#中控制datagridview光标移动

    我希望 datagridview 光标向右移动到下一列 而不是在向单元格输入数据后移动到下一行 我试图通过 dataGridView1 KeyDown 事件捕获键来控制光标 但这并不能阻止光标在将数据输入到单元格后移动到下一行 提前感谢你的
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 在 C# 的 WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据

    我需要服务分块传输使用编码数据API控制器 因为我无权访问HttpContext or the Http请求 我有点不知道在哪里写入响应以及在哪里刷新它 设置如下 public class MyController ApiControlle
  • 任何人都可以清楚地告诉如何在不使用像 这样的预定义函数的情况下找到带有小数值或小数值的指数吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 例如 2 0 5 1 414 所以想要 我是 c 的新手 所以请解释简单的逻辑 如果不是复杂的逻辑也足够了 在数学中 从整数取幂到实数
  • 如何组合两个 lambda [重复]

    这个问题在这里已经有答案了 可能的重复 在 C 中组合两个 lambda 表达式 https stackoverflow com questions 1717444 combining two lamba expressions in c
  • 将键码转换为相关的显示字符

    在 C Windows Forms 项目中 我有一个不提供 KeyPressed 事件的控件 它是一个 COM 控件 ESRI 映射 它仅提供 KeyUp 和 KeyDown 事件 包含关键事件参数 http msdn microsoft
  • winform c# 中的弹出窗口

    我正在开发一个需要弹出窗口的项目 但问题是我还希望能够通过表单设计器在此弹出窗口中添加文本框等 所以基本上我有一个按钮 当您单击它时 它将打开我在表单设计器中设计的另一个窗口 我一直在谷歌搜索 但还没有找到我需要的东西 所以我希望你们能帮助

随机推荐

  • 关于Java Servlet使用iText打开PDF文件的问题

    下面的代码获取 PDF 文件并将其显示在浏览器中 import java io ByteArrayOutputStream import java io FileInputStream import java io FileOutputSt
  • 如何正确使用 SSL_read() 和 select()?

    我尝试使用 OpenSSL 创建一个 C TLS 客户端 它在 Windows 上使用非阻塞套接字 我想使用 SSL read SSL write 和 select 函数 但我找不到运行良好的算法 并且网络没有提供良好且简单的示例 在接收最
  • 将 [audio ] 转换为核心 php 中的 标签

    我在将链接转换为 tag 时遇到麻烦 这是 我在尝试 audio mp3 https abcd com wp content uploads sites 2 2020 03 classical demo mp3 audio 转换 a hre
  • AVAudioEngine.connect 在硬件而非模拟器上崩溃

    var engine AVAudioEngine var format engine inputNode inputFormat forBus 0 engine connect engine inputNode to engine main
  • 通过 sbt 打包的 one-jar 内的类路径资源

    我有一个使用 SBT 构建的项目 它使用 one jar 插件打包单个 jar 该项目在 src main resources fixture 中包含一堆 json 文件 我曾经通过以下方式访问它们 new java io File App
  • 我可以在内核空间中拥有超过 32 个 netlink 套接字吗?

    我有几个需要与用户空间交互的内核模块 因此 每个模块都有一个 Netlink 套接字 我的问题是这些套接字相互干扰 这是因为它们都注册到同一个 Netlink 地址族 因为一开始可用的地址族并不多 最大值为 32 and 一半以上已被预订
  • 408 请求超时 Microsoft Speech to Text

    我的 wav 文件长度只有 4 秒 即使多次重试并在云上运行后 我仍然不断收到以下错误 upload completely sent off 12 out of 12 bytes lt HTTP 1 1 408 Request timed
  • 数据库设计:复合键与一列主键

    我们的 Web 应用程序的数据库包含两个表 States idStates State Lat Long idStates是一个自增主键 Cities idAreaCode idStates City Lat Long idAreaCode
  • 分支逻辑测验——我哪里出错了? [JavaScript]

    我正在尝试为 简单 jQuery 测验开发逻辑 这里小提琴 问题是 问题路径有些动态 并产生树结构 例如 第一个问题是关于宠物 狗 猫还是鸟 如果您选择狗 它会询问狗的品种 如果您选择猫 它会询问猫的品种 等等 然后深入研究 这个特定品种的
  • ruby 中“do .. end”和“{..}”块的不同行为[重复]

    这个问题在这里已经有答案了 抱歉 如果这个问题重复 但我找不到用法上的区别 当我运行下面的代码时 我得到了不同的答案 我从大多数教程中看到 使用 do end 与 块相同 include Comparable a 1 4 2 3 5 p a
  • 如何使用实体框架 4.x 动态选择表?

    假设我有一个名为MyDatabase有两张桌子 MyTable1 and MyTable2 使用 Entity Framework 4 x 和 NET 4 的 Code First 方法 我生成了一个名为的上下文MyDatabaseCont
  • CSS中使用渐变效果反射文本

    我需要用 CSS 反射文本并为其添加渐变 这是一个例子我想要的 但我不想要具有 alpha 透明度的淡出 png 图像因为身体有背景 https jsfiddle net 9318Ltkp slogan font size 30px lin
  • 仅存档时出现 ARC 语义问题“多个名为‘setRotation’的方法”

    我在 cocos2dv3 中的项目正在抛出ARC语义问题发现多个名为 setRotation 的方法 其结果 参数类型或属性不匹配 归档时 发布模式 它在部署到模拟器 设备 调试模式 时运行良好 在发布模式下 编译器会混淆旋转的实现UIRo
  • 如何使安全令牌在被动 STS 设置中自动过期?

    我为我正在开发的新应用程序设置了被动 STS 我注意到 当用户的会话过期时 该用户仍然经过身份验证 我本以为当会话过期时 用户将不再被验证 我的老板与我讨论了这个问题 因为我目前负责设置身份验证 他说 如果我们能让用户的登录在一段时间内不活
  • 崩溃加载可穿戴活动

    将 AppCompatActivity 迁移到 WearableActivity 时 我收到崩溃消息 并显示以下消息 引起原因 java lang IllegalStateException 找不到可穿戴设备 共享库类 请添加uses li
  • 对象 # 的属性“submit”不是函数

    谁能向我解释这个错误意味着什么 如果您能提供任何帮助 我将非常感激
  • log4j:ERROR setFile(null,false) 调用失败

    我面临一些奇怪的错误 如下所示 log4j ERROR setFile null false call failed java io FileNotFoundException debug log Access is denied src
  • TCL:execegrep“子进程异常退出”

    我的egrep命令有问题 当我在 tcsh 中执行命令时 它工作正常 但是当我从 tcl 脚本或在 tclsh 中执行它时 我得到 子进程异常退出 grep 使用其退出状态来指示存在 不存在匹配项 man page 如果没有匹配 则退出状态
  • 为什么使用 boost::copy_exception 时会丢失类型信息?

    当我使用boost copy exception将异常复制到exception ptr 我丢失了类型信息 看一下下面的代码 try throw std runtime error something catch exception e pt
  • 在 .NET Core 中的 MVC 之外使用 Razor

    我想在我用 NET Core 编写的 NET 控制台应用程序中使用 Razor 作为模板引擎 我遇到的独立 Razor 引擎 RazorEngine RazorTemplates 都需要完整的 NET 我正在寻找适用于 NET Core 的