在 ASP.NET 5 中将 Razor 视图呈现为字符串

Posted

技术标签:

【中文标题】在 ASP.NET 5 中将 Razor 视图呈现为字符串【英文标题】:Render Razor view to string in ASP.NET 5 【发布时间】:2015-08-02 10:30:03 【问题描述】:

在以前的 ASP.NET 版本中,虽然不是很简单,但可以将 Razor 视图呈现为字符串。我的方法似乎是使用假控制器,或者也使用一些外部引擎,如RazorEngine。

现在,ASP.NET 5 改变了很多东西,我想知道这是否比以前更简单了。那么在新版本的框架中是否有一种直接的方法可以将 Razor 视图呈现为字符串,或者我们仍然需要使用以前版本中的方法?

【问题讨论】:

是否要将动作的 html 内容插入到字符串变量中?或者干脆在另一个视图中渲染一个 ActionResult? @FabioLuz 我想渲染视图并将渲染的 HTML 代码放在字符串变量中。 如果您想在 MVC 6 下执行此操作,应该相当简单。这只是获得正确的依赖关系来排列剃刀视图的问题。但是,如果您不在其中,这里有一个示例:github.com/tugberkugurlu/RazorOnConsole/blob/… 深入了解Templater.Run 是如何实现的。 @tugberk 这个链接很棒,谢谢!我不是 OP,但你的 repo 非常有帮助。 【参考方案1】:

我使用从IServiceProvider注入的以下类型:

ICompositeViewEngine viewEngine;
ITempDataProvider tempDataProvider;
IHttpContextAccessor httpContextAccessor;

我使用以下方法渲染内容:

private async Task<string> RenderView(string path, ViewDataDictionary viewDataDictionary, ActionContext actionContext)

    using (var sw = new System.IO.StringWriter())
    
        var viewResult = viewEngine.FindView(actionContext, path);

        var viewContext = new ViewContext(actionContext, viewResult.View, viewDataDictionary, new TempDataDictionary(httpContextAccessor, tempDataProvider), sw);

        await viewResult.View.RenderAsync(viewContext);
        sw.Flush();

        if (viewContext.ViewData != viewDataDictionary)
        
            var keys = viewContext.ViewData.Keys.ToArray();
            foreach (var key in keys)
            
                viewDataDictionary[key] = viewContext.ViewData[key];
            
        

        return sw.ToString();
    

我这样称呼它:

var path = "~/Views/Home/Index.cshtml";
var viewDataDictionary = new ViewDataDictionary(new Microsoft.AspNet.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNet.Mvc.ModelBinding.ModelStateDictionary());
var actionContext = new ActionContext(httpContextAccessor.HttpContext, new Microsoft.AspNet.Routing.RouteData(), new ActionDescriptor());
viewDataDictionary.Model = null;
var text = await RenderView(path, viewDataDictionary, actionContext);

当然,我的viewDataDictionaryactionContext变量是通过另外一种封装方式设置的。如果您愿意,对new ViewDataDictionary 行的修改可能会导致类型化模型绑定到您的视图。

这段代码使用了大量的用法,我想我已经在下面列出了它们。否则,VS2015 很适合找到它们。

using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;

这是在 beta-3 下编写的;它仍在构建,但有些事情可能会改变。如果有,我会尝试回到这里更新。

【讨论】:

很高兴为您提供帮助!感谢您注意到它仍然有效 - 我不必回去更改它,所以没有在我的答案中添加该注释。 没有看到你是如何获得这些注入对象的,而且方法的签名与你调用它的方式不一致...... @Shockwaver - 以防万一有人对此感到疑惑,这只是依赖注入 (DI)。服务依赖项通常是类的构造函数的参数,DI 容器会计算出从哪里获取它们。关于签名不一致,Matt 可能在具有 ActionContext 属性的控制器中编写了原始方法,因此您只需更改为大写 A 并开始从控制器中测试代码。【参考方案2】:

我在一年前使用过一个解决方案。我不确定是否有新的/更好的方法,但它可以解决问题。

public string RenderViewToString(string viewName, object model)

    ViewData.Model = model;
    using (var sw = new StringWriter())
    
       var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
       var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
       viewResult.View.Render(viewContext, sw);
       viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
       return sw.GetStringBuilder().ToString();
     

【讨论】:

不幸的是,asp.net-5 中也不存在 ViewEngines 类。 @MattDeKrey 但它在 v4 中确实如此(不是 OP 请求,我知道)! Aaand 这绝对是该版本的最佳选择!不错,节省了我的一天,与剃须刀一起使用的任何 html 助手都没有问题。谢谢你

以上是关于在 ASP.NET 5 中将 Razor 视图呈现为字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 Razor (chtml) 中渲染动态视图,如何在 asp.net core 3.0 中将 FileProvider 添加到 razor?

在 ASP.NET MVC 5 中从数据库加载 Razor 视图

HTML 编码字符串 - ASP.NET Web 窗体 VS Razor 视图引擎

ASP .NET Core 5 Razor Pages:如何正确使用局部视图并验证其模型状态?

如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?

[Asp.Net Core]MVC开发&解读Razor混编