在.NET Core中将视图返回为字符串

我发现了一些文章如何在ASP.NET中将视图返回到字符串,但无法转换为能够使用.NET Core运行它

public static string RenderViewToString(this Controller controller, string viewName, object model) { var context = controller.ControllerContext; if (string.IsNullOrEmpty(viewName)) viewName = context.RouteData.GetRequiredString("action"); var viewData = new ViewDataDictionary(model); using (var sw = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(context, viewName); var viewContext = new ViewContext(context, viewResult.View, viewData, new TempDataDictionary(), sw); viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } } 

假设能够使用以下控制器从控制器调用:

 var strView = this.RenderViewToString("YourViewName", yourModel); 

当我尝试将上述内容运行到.NET Core时,我遇到了很多编译错误。

我试图将其转换为使用.NET Core,但失败了,任何人都可以帮助提及所需的using ..和所需的"dependencies": { "Microsoft.AspNetCore.Mvc": "1.1.0", ... },project.json

其他一些示例代码在这里 , 这里和这里

注意我需要解决方案来将视图转换为.NET Core中的string ,无论相同的代码是否已转换,或者其他方式可以执行此操作。

感谢Paris Polyzos和他的文章 。

我在这里重新发布他的代码,以防原始post因任何原因被删除。

在文件viewToString.cs创建Service ,如下代码:

 using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; namespace WebApplication.Services {    public interface IViewRenderService    {        Task RenderToStringAsync(string viewName, object model);    }    public class ViewRenderService : IViewRenderService    {        private readonly IRazorViewEngine _razorViewEngine;        private readonly ITempDataProvider _tempDataProvider;        private readonly IServiceProvider _serviceProvider;        public ViewRenderService(IRazorViewEngine razorViewEngine,            ITempDataProvider tempDataProvider,            IServiceProvider serviceProvider)        {            _razorViewEngine = razorViewEngine;            _tempDataProvider = tempDataProvider;            _serviceProvider = serviceProvider;        }        public async Task RenderToStringAsync(string viewName, object model)        {            var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());            using (var sw = new StringWriter())            {                var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);                if (viewResult.View == null)                {                    throw new ArgumentNullException($"{viewName} does not match any available view");                }                var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())                {                    Model = model                };                var viewContext = new ViewContext(                    actionContext,                    viewResult.View,                    viewDictionary,                    new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),                    sw,                    new HtmlHelperOptions()                );                await viewResult.View.RenderAsync(viewContext);                return sw.ToString();            }        }    } } 
  1. 将服务添加到Startup.cs文件中,如下所示:

     using WebApplication.Services; public void ConfigureServices(IServiceCollection services) { ...    services.AddScoped(); } 

"preserveCompilationContext": true添加到project.jsonbuildOptions ,因此该文件如下所示:

 { "version": "1.0.0-*", "buildOptions": { "debugType": "portable", "emitEntryPoint": true, "preserveCompilationContext": true }, "dependencies": { "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", "Microsoft.AspNetCore.Mvc": "1.0.1" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.1" } }, "imports": "dnxcore50" } } } 
  1. 定义model ,例如:

     public class InviteViewModel { public string UserId {get; set;} public string UserName {get; set;} public string ReferralCode {get; set;} public int Credits {get; set;} } 
  2. 例如,创建Invite.cshtml

     @{ ViewData["Title"] = "Contact"; } @ViewData["Title"]. user id: @Model.UserId 
  3. Controller

一个。 在开头定义以下内容:

 private readonly IViewRenderService _viewRenderService; public RenderController(IViewRenderService viewRenderService) { _viewRenderService = viewRenderService; } 

湾 使用模型调用并返回视图,如下所示:

 var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel); return Content(result); 

C。 FULL控制器示例可能如下:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using WebApplication.Services; namespace WebApplication.Controllers { [Route("render")] public class RenderController : Controller { private readonly IViewRenderService _viewRenderService; public RenderController(IViewRenderService viewRenderService) { _viewRenderService = viewRenderService; } [Route("invite")] public async Task RenderInviteView() { ViewData["Message"] = "Your application description page."; var viewModel = new InviteViewModel { UserId = "cdb86aea-e3d6-4fdd-9b7f-55e12b710f78", UserName = "Hasan", ReferralCode = "55e12b710f78", Credits = 10 }; var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel); return Content(result); } } public class InviteViewModel { public string UserId {get; set;} public string UserName {get; set;} public string ReferralCode {get; set;} public int Credits {get; set;} } } 

如果像我一样你有许多需要这个的控制器,比如报告网站,重复这个代码并不是很理想,甚至注入或调用另一个服务似乎并不合适。

所以我已经制作了我自己的上述版本,但有以下不同之处:

  • 模型强类型
  • 查找视图时的错误检查
  • 将视图呈现为部分或页面的能力
  • asynchronus
  • 实现为控制器扩展
  • 不需要DI

     using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures; using System.IO; using System.Threading.Tasks; namespace CC.Web.Helpers { public static class ControllerExtensions { public static async Task RenderViewAsync(this Controller controller, string viewName, TModel model, bool partial = false) { if (string.IsNullOrEmpty(viewName)) { viewName = controller.ControllerContext.ActionDescriptor.ActionName; } controller.ViewData.Model = model; using (var writer = new StringWriter()) { IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, !partial); if (viewResult.Success == false) { return $"A view with the name {viewName} could not be found"; } ViewContext viewContext = new ViewContext( controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, writer, new HtmlHelperOptions() ); await viewResult.View.RenderAsync(viewContext); return writer.GetStringBuilder().ToString(); } } } } 

然后执行:

 viewHtml = await this.RenderViewAsync("Report", model); 

或者这对于PartialView:

 partialViewHtml = await this.RenderViewAsync("Report", model, true); 

上面的答案很好,但需要调整以使任何标记助手工作(我们需要使用实际的http上下文)。 此外,您还需要在视图中显式设置布局以获取呈现的布局。

 public class ViewRenderService : IViewRenderService { private readonly IRazorViewEngine _razorViewEngine; private readonly ITempDataProvider _tempDataProvider; private readonly IServiceProvider _serviceProvider; private readonly IHostingEnvironment _env; private readonly HttpContext _http; public ViewRenderService(IRazorViewEngine razorViewEngine, ITempDataProvider tempDataProvider, IServiceProvider serviceProvider, IHostingEnvironment env, IHttpContextAccessor ctx) { _razorViewEngine = razorViewEngine; _tempDataProvider = tempDataProvider; _serviceProvider = serviceProvider; _env = env; _http = ctx.HttpContext; } public async Task RenderToStringAsync(string viewName, object model) { var actionContext = new ActionContext(_http, new RouteData(), new ActionDescriptor()); using (var sw = new StringWriter()) { var viewResult = _razorViewEngine.FindView(actionContext, viewName, false); //var viewResult = _razorViewEngine.GetView(_env.WebRootPath, viewName, false); // For views outside the usual Views folder if (viewResult.View == null) { throw new ArgumentNullException($"{viewName} does not match any available view"); } var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; var viewContext = new ViewContext(actionContext, viewResult.View, viewDictionary, new TempDataDictionary(_http, _tempDataProvider), sw, new HtmlHelperOptions()); viewContext.RouteData = _http.GetRouteData(); await viewResult.View.RenderAsync(viewContext); return sw.ToString(); } } } 

下面的链接解决了几乎相同的问题:

MVC 6 Controller中的ControllerContext和ViewEngines属性在哪里?

在Hasan A Yousef的回答中,我必须进行与上面链接相同的更改,以使其适用于我:

 using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; using System; using System.IO; using System.Threading.Tasks; public class ViewRenderService : IViewRenderService { private readonly IRazorViewEngine _razorViewEngine; private readonly ITempDataProvider _tempDataProvider; private readonly IServiceProvider _serviceProvider; private readonly IHostingEnvironment _env; public ViewRenderService(IRazorViewEngine razorViewEngine, ITempDataProvider tempDataProvider, IServiceProvider serviceProvider, IHostingEnvironment env) { _razorViewEngine = razorViewEngine; _tempDataProvider = tempDataProvider; _serviceProvider = serviceProvider; _env = env; } public async Task RenderToStringAsync(string viewName, object model) { var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider }; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); using (var sw = new StringWriter()) { //var viewResult = _razorViewEngine.FindView(actionContext, viewName, false); var viewResult = _razorViewEngine.GetView(_env.WebRootPath, viewName, false); if (viewResult.View == null) { throw new ArgumentNullException($"{viewName} does not match any available view"); } var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; var viewContext = new ViewContext(actionContext, viewResult.View, viewDictionary, new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), sw, new HtmlHelperOptions()); await viewResult.View.RenderAsync(viewContext); return sw.ToString(); } } 

微软有一篇关于控制器测试的优秀文章,请访问https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/testing

返回ViewResult后,您可以获取字符串内容

var strResult = ViewResult.Content