You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级至ASP.NET Core 2.1.0后自定义RazorTemplateEngine失效

解决ASP.NET Core 2.1中自定义RazorTemplateEngine失效的问题

这个问题的核心原因是ASP.NET Core 2.1对Razor视图编译系统做了重大调整——框架不再直接注入RazorTemplateEngine实例,而是通过IRazorTemplateEngineFactory工厂接口来创建模板引擎。你之前直接注册CustomRazorTemplateEngine单例的方式,已经无法被框架识别和调用了。

下面是修复后的完整方案:

1. 实现自定义的IRazorTemplateEngineFactory

我们需要创建一个工厂类,负责生成你的自定义模板引擎实例,让框架能够正确获取到它:

using Microsoft.AspNetCore.Razor.Language;

public class CustomRazorTemplateEngineFactory : IRazorTemplateEngineFactory
{
    private readonly RazorEngine _engine;
    private readonly RazorProject _project;
    private readonly HtmlMinifier _htmlMinifier;

    public CustomRazorTemplateEngineFactory(RazorEngine engine, RazorProject project)
    {
        _engine = engine;
        _project = project;
        _htmlMinifier = new HtmlMinifier();
    }

    public RazorTemplateEngine Create()
    {
        var customEngine = new CustomRazorTemplateEngine(_engine, _project, _htmlMinifier);
        customEngine.Options.ImportsFileName = "_ViewImports.cshtml";
        return customEngine;
    }
}

2. 调整自定义RazorTemplateEngine的实现

把HtmlMinifier通过构造函数注入(解耦依赖,也方便后续扩展),同时修复原代码中可能出现的索引越界问题:

using System.IO;
using System.Text;
using Microsoft.AspNetCore.Razor.Language;

public class CustomRazorTemplateEngine : RazorTemplateEngine
{
    private readonly HtmlMinifier _htmlMinifier;

    public CustomRazorTemplateEngine(RazorEngine engine, RazorProject project, HtmlMinifier htmlMinifier) 
        : base(engine, project)
    {
        _htmlMinifier = htmlMinifier;
    }

    public override RazorCodeDocument CreateCodeDocument(RazorProjectItem projectItem)
    {
        using (var inputStream = projectItem.Read())
        using (var reader = new StreamReader(inputStream))
        {
            var text = reader.ReadToEnd();
            var markupStart = text.IndexOf("<!DOCTYPE");
            
            // 处理视图中没有DOCTYPE的情况,避免索引越界
            if (markupStart == -1)
            {
                markupStart = 0;
            }

            var directives = text.Substring(0, markupStart);
            var markup = text.Substring(markupStart);
            text = directives + Minify(markup);

            var byteArray = Encoding.UTF8.GetBytes(text);
            using (var minifiedInputStream = new MemoryStream(byteArray))
            {
                var source = RazorSourceDocument.ReadFrom(minifiedInputStream, projectItem.PhysicalPath);
                var imports = GetImports(projectItem);
                return RazorCodeDocument.Create(source, imports);
            }
        }
    }

    private string Minify(string markup)
    {
        var result = _htmlMinifier.Minify(markup, string.Empty, Encoding.UTF8, true);
        
        if (result.Errors.Count == 0)
        {
            var statistics = result.Statistics;
            if (statistics != null)
            {
                Console.WriteLine();
                Console.WriteLine($"Original size: {statistics.OriginalSize:N0} Bytes | Minified size: {statistics.MinifiedSize:N0} Bytes | Saved: {statistics.SavedInPercent:N2}%");
            }
            return result.MinifiedContent;
        }
        else
        {
            Console.WriteLine();
            Console.WriteLine($"Found {result.Errors.Count:N0} error(s):");
            foreach (var error in result.Errors)
            {
                Console.WriteLine($" - Line {error.LineNumber}, Column {error.ColumnNumber}: {error.Message}");
            }
            return markup;
        }
    }
}

3. 注册自定义工厂到服务容器

替换你原来的services.AddSingleton<CustomRazorTemplateEngine>();,改为注册工厂接口:

// Startup.cs 中的 ConfigureServices 方法
services.AddSingleton<IRazorTemplateEngineFactory, CustomRazorTemplateEngineFactory>();

为什么原来的方案失效?

在ASP.NET Core 2.1之前,框架直接依赖RazorTemplateEngine实例来处理视图编译,但2.1版本引入了Razor SDK的优化,改用IRazorTemplateEngineFactory来管理模板引擎的创建逻辑。这意味着你之前注册的CustomRazorTemplateEngine单例根本不会被框架调用,自然重写的CreateCodeDocument方法也不会执行。

额外提示:如果你的项目使用了预编译视图,可能需要在项目文件中添加额外配置来启用运行时编译支持,否则自定义压缩逻辑可能不会生效。

内容的提问来源于stack exchange,提问作者Adem Çınar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:13:38