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

ASP.NET Core MVC中如何渲染存储在Model属性中的Cshtml内容

Html.Raw仅负责将字符串跳过HTML编码直接输出,不具备Razor语法解析、变量绑定能力,因此无法解析模板中的@Model.Property片段,你需要对存储的Razor模板做动态编译渲染,以下是两种可落地的实现方案:

方案1:基于ASP.NET Core内置组件实现动态Razor渲染

无需引入第三方依赖,通过IRazorViewEngine实现模板的动态编译与渲染:

  • 第一步:封装动态渲染服务
public interface IRazorTemplateRenderer
{
    Task<string> RenderToStringAsync(string templateContent, object model);
}

public class RazorTemplateRenderer : IRazorTemplateRenderer
{
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public RazorTemplateRenderer(IRazorViewEngine razorViewEngine,
        ITempDataProvider tempDataProvider,
        IHttpContextAccessor httpContextAccessor)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<string> RenderToStringAsync(string templateContent, object model)
    {
        var httpContext = _httpContextAccessor.HttpContext ?? new DefaultHttpContext { RequestServices = BuildServiceProvider() };
        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

        using var sw = new StringWriter();
        var dynamicPage = new DynamicRazorPage($"DynamicTemplate_{Guid.NewGuid()}", templateContent);
        var view = new RazorView(_razorViewEngine,
            Enumerable.Empty<IRazorPageFactoryProvider>(),
            Enumerable.Empty<IRazorPageActivator>(),
            new HtmlHelperOptions(),
            new RazorViewOptions(),
            dynamicPage,
            Enumerable.Empty<IControllerPropertyActivator>());

        var viewContext = new ViewContext(
            actionContext,
            view,
            new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model },
            new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
            sw,
            new HtmlHelperOptions()
        );

        await view.RenderAsync(viewContext);
        return sw.ToString();
    }

    private IServiceProvider BuildServiceProvider()
    {
        var services = new ServiceCollection();
        services.AddSingleton(_razorViewEngine);
        services.AddSingleton(_tempDataProvider);
        return services.BuildServiceProvider();
    }
}

// 自定义动态Razor页加载模板内容
public class DynamicRazorPage : IRazorPage
{
    private readonly string _templateContent;
    public DynamicRazorPage(string path, string templateContent)
    {
        Path = path;
        _templateContent = templateContent;
    }
    public async Task ExecuteAsync() => await Output.WriteAsync(_templateContent);
    public string Path { get; }
    public ViewContext ViewContext { get; set; }
    public TextWriter Output { get; set; }
    public bool IsLayoutBeingRendered { get; set; }
    public string Layout { get; set; }
    public IDictionary<string, RenderAsyncDelegate> PreviousSectionWriters { get; set; }
    public IDictionary<string, RenderAsyncDelegate> SectionWriters { get; } = new Dictionary<string, RenderAsyncDelegate>();
}
  • 第二步:注册服务,在Program.cs中添加如下配置:
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IRazorTemplateRenderer, RazorTemplateRenderer>();
  • 第三步:控制器中调用渲染逻辑
public async Task<IActionResult> Index()
{
    // 从数据库读取存储的cshtml模板
    var dbTemplate = await _yourDbContext.PageTemplates.FindAsync(templateId);
    // 构造需要绑定的业务Model
    var pageModel = new YourPageModel { Property = "需要插入的属性值" };
    // 渲染得到最终HTML
    var finalHtml = await _razorTemplateRenderer.RenderToStringAsync(dbTemplate.Content, pageModel);
    // 传递到视图
    ViewBag.FinalHtml = finalHtml;
    return View(pageModel);
}
  • 第四步:视图中直接输出渲染结果
@Html.Raw(ViewBag.FinalHtml)
方案2:轻量场景下的字符串替换方案

如果存储的模板只有简单的@Model.xxx变量引用,没有循环、判断、嵌套调用等复杂Razor语法,可以用反射实现变量批量替换,性能远高于动态编译:

public string ReplaceTemplateVariables(string template, object model)
{
    var properties = model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var prop in properties)
    {
        var value = prop.GetValue(model)?.ToString() ?? string.Empty;
        template = template.Replace($"@Model.{prop.Name}", value);
    }
    return template;
}

替换后的字符串直接用@Html.Raw输出即可。

注意事项

  • 动态编译模板存在一定性能开销,建议对不变的模板加缓存,避免每次请求重复编译
  • 若存储的模板支持用户自定义编辑,需做好安全校验,避免恶意代码注入风险

内容的提问来源于stack exchange,提问作者Peej

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 07:09:02