Вернуть представление в виде строки в.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
,
некоторые другие примеры кодов здесь и здесь и здесь
ПРИМЕЧАНИЕ. Мне нужно решение, чтобы преобразовать вид в string
в.NET Core, независимо от того, какой код был преобразован или каким-либо другим способом.
13 ответов
Спасибо Пэрис Полизос и его статье.
Я повторно публикую его код здесь, на случай, если оригинальное сообщение будет удалено по какой-либо причине.
Создайте Service
в файле viewToString.cs
как ниже код:
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<string> 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<string> 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();
}
}
}
}
Добавьте сервис в
Startup.cs
файл, как:using WebApplication.Services; public void ConfigureServices(IServiceCollection services) { ... services.AddScoped<IViewRenderService, ViewRenderService>(); }
добавлять "preserveCompilationContext": true
к buildOptions
в project.json
так файл выглядит так:
{
"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"
}
}
}
Определить вас
model
, например:public class InviteViewModel { public string UserId {get; set;} public string UserName {get; set;} public string ReferralCode {get; set;} public int Credits {get; set;} }
Создайте свой
Invite.cshtml
например:@{ ViewData["Title"] = "Contact"; } @ViewData["Title"]. user id: @Model.UserId
в
Controller
:
а. Определите ниже в начале:
private readonly IViewRenderService _viewRenderService;
public RenderController(IViewRenderService viewRenderService)
{
_viewRenderService = viewRenderService;
}
б. Позвоните и верните вид с моделью, как показано ниже:
var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel);
return Content(result);
с. Пример 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<IActionResult> 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<string> RenderViewAsync<TModel>(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);
Ответ Реда дал мне 99% пути, но он не работает, если ваши взгляды находятся в неожиданном месте. Вот мое решение для этого.
using Microsoft.AspNetCore.Hosting;
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 Example
{
public static class ControllerExtensions
{
public static async Task<string> RenderViewAsync<TModel>(this Controller controller, string viewName, TModel model, bool isPartial = 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 = GetViewEngineResult(controller, viewName, isPartial, viewEngine);
if (viewResult.Success == false)
{
throw new System.Exception($"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();
}
}
private static ViewEngineResult GetViewEngineResult(Controller controller, string viewName, bool isPartial, IViewEngine viewEngine)
{
if (viewName.StartsWith("~/"))
{
var hostingEnv = controller.HttpContext.RequestServices.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;
return viewEngine.GetView(hostingEnv.WebRootPath, viewName, !isPartial);
}
else
{
return viewEngine.FindView(controller.ControllerContext, viewName, !isPartial);
}
}
}
}
Это позволяет использовать его, как показано ниже:
var emailBody = await this.RenderViewAsync("~/My/Different/View.cshtml", myModel);
ASP.NET Core 3.1
Я знаю, что здесь много хороших ответов, я думал, что тоже поделюсь своими:
Это извлекается из исходного кода ядра as p.net на GitHub. Я обычно использую его для рендеринга электронных писем HTML с помощью Razor, а также для возврата HTML частичных представлений через Ajax или SignalR.
Добавить как временную службу и внедрить с помощью DI в контроллеры
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.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
public sealed class RazorViewToStringRenderer : IRazorViewToStringRenderer
{
private readonly IRazorViewEngine _viewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider;
public RazorViewToStringRenderer(
IRazorViewEngine viewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_viewEngine = viewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
}
public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
{
//If you wish to use the route data in the generated view (e.g. use
//the Url helper to construct dynamic links)
//inject the IHttpContextAccessor then use: var actionContext = new ActionContext(_contextAccessor.HttpContext, _contextAccessor.HttpContext.GetRouteData(), new ActionDescriptor());
//instead of the line below
var actionContext = GetActionContext();
var view = FindView(actionContext, viewName);
using (var output = new StringWriter())
{
var viewContext = new ViewContext(
actionContext,
view,
new ViewDataDictionary<TModel>(
metadataProvider: new EmptyModelMetadataProvider(),
modelState: new ModelStateDictionary())
{
Model = model
},
new TempDataDictionary(
actionContext.HttpContext,
_tempDataProvider),
output,
new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return output.ToString();
}
}
private IView FindView(ActionContext actionContext, string viewName)
{
var getViewResult = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
if (getViewResult.Success)
{
return getViewResult.View;
}
var findViewResult = _viewEngine.FindView(actionContext, viewName, isMainPage: true);
if (findViewResult.Success)
{
return findViewResult.View;
}
var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations);
var errorMessage = string.Join(
Environment.NewLine,
new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations)); ;
throw new InvalidOperationException(errorMessage);
}
private ActionContext GetActionContext()
{
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = _serviceProvider;
return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
}
}
public interface IRazorViewToStringRenderer
{
Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model);
}
АСП .NET 5
Здесь уже было опубликовано много отличных ответов. По сути, у меня была аналогичная проблема, когда я хотел прочитать шаблон электронной почты со страницы бритвы (.cshtml) в виде строки, и я столкнулся с этим вопросом и попробовал все ответы. Я столкнулся с некоторыми проблемами в .NET 5, поэтому я публикую здесь свое слегка измененное решение. Спасибо.
Startup.cs
файл
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<CustomViewRendererService>();
...
}
CustomViewRendererService.cs
файл
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.IO;
using System.Threading.Tasks;
namespace Services
{
public class CustomViewRendererService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
public CustomViewRendererService(
IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
}
public async Task<string> RenderViewToStringAsync(ControllerContext actionContext, string viewPath, object model)
{
var viewEngineResult = _razorViewEngine.GetView(viewPath, viewPath, false);
if (viewEngineResult.View == null || (!viewEngineResult.Success))
{
throw new ArgumentNullException($"Unable to find view '{viewPath}'");
}
var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), actionContext.ModelState);
viewDictionary.Model = model;
var view = viewEngineResult.View;
var tempData = new TempDataDictionary(actionContext.HttpContext, _tempDataProvider);
using var sw = new StringWriter();
var viewContext = new ViewContext(actionContext, view, viewDictionary, tempData, sw, new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return sw.ToString();
}
}
}
В моем контроллере
public class TestController : ControllerBase
{
private readonly CustomViewRendererService _viewService;
public TestController(CustomViewRendererService viewService)
{
_viewService = viewService;
}
public async Task<IActionResult> SendTestEmail2Async()
{
var templatePath = "~/Views/Email/Test.cshtml";
var msg = await _viewService.RenderViewToStringAsync(ControllerContext, templatePath, ("Foo", "Bar"));
return Ok(msg);
}
}
в конце концов
Test.cshtml
файл
@model (string arg1, string arg2)
<h1>Param: @Model.arg1</h1>
<h1>Param @Model.arg2</h1>
Ответы выше хороши, но нужно настроить, чтобы работали какие-либо помощники тегов (нам нужно использовать фактический 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<string> 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();
}
}
}
Я, вероятно, опаздываю на вечеринку, но мне удалось найти решение, которое работает без создания экземпляра нового механизма просмотра (RazorViewEngine), но фактически повторно использует механизм просмотра, уже доступный в каждом из контроллеров. Кроме того, при таком подходе мы также получаем помощь от IntelliSense при вводе имени представления, что действительно полезно при попытке определить точный путь представления.
Итак, при таком подходе ваш код будет выглядеть так:
public override async Task<IActionResult> SignUp()
{
...
// send an email notification
var emailView = View("Emails/SignupNotification"); // simply get the email view
var emailBody = await RenderToStringAsync(emailView, _serviceProvider); // render it as a string
SendEmail(emailBody);
...
return View();
}
В RenderToStringAsync
Метод, используемый в этом примере, выглядит так:
private static async Task<string> RenderToStringAsync(ViewResult viewResult, IServiceProvider serviceProvider)
{
if (viewResult == null) throw new ArgumentNullException(nameof(viewResult));
var httpContext = new DefaultHttpContext
{
RequestServices = serviceProvider
};
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
using (var stream = new MemoryStream())
{
httpContext.Response.Body = stream; // inject a convenient memory stream
await viewResult.ExecuteResultAsync(actionContext); // execute view result on that stream
httpContext.Response.Body.Position = 0;
return new StreamReader(httpContext.Response.Body).ReadToEnd(); // collect the content of the stream
}
}
Если вы реализуете метод как метод расширения, ваше использование может стать:
public override async Task<IActionResult> SignUp()
{
...
var emailBody = View("Emails/SignupNotification")
.RenderToStringAsync(_serviceProvider);
...
return View();
}
Я написал чистую библиотеку Razor.Templating.Core, которая работает с.NET Core 3.0, 3.1 как в веб-приложении, так и в консольном приложении. Он доступен как пакет NuGet. После установки можно звонить как
var htmlString = await RazorTemplateEngine
.RenderAsync("/Views/ExampleView.cshtml", model, viewData);
Примечание. Приведенный выше фрагмент не будет работать сразу. Пожалуйста, обратитесь к рабочему руководству ниже, чтобы узнать, как его применять.
Полное рабочее руководство: https://medium.com/@soundaranbu/render-razor-view-cshtml-to-string-in-net-core-7d125f32c79
Примеры проектов: https://github.com/soundaranbu/RazorTemplating/tree/master/examples
Я попробовал решение, на которое ответил @Hasan A Yousef в Dotnet Core 2.1, но csthml мне не подходит. Всегда выдает исключение NullReferenceException, см. Скриншот.
Чтобы решить эту проблему, я назначаю Html.ViewData.Model новому объекту. Вот мой код
@page
@model InviteViewModel
@{
var inviteViewModel = Html.ViewData.Model;
}
<p>
<strong>User Id:</strong> <code>@inviteViewModel.UserId </code>
</p>
Ссылка ниже решает практически ту же проблему:
Где находятся свойства ControllerContext и ViewEngines в MVC 6 Controller?
В ответе Хасана Юсефа я должен был внести те же изменения, что и в приведенной выше ссылке, чтобы заставить меня работать:
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<string> 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();
}
}
Вот еще одна версия, которая мне больше подошла, но все еще очень похожа на другие версии выше. Это Core MVC 3.X.
Контроллер:
public IActionResult UserClientView(UserClientModel ucm)
{
try
{
PartialViewResult pvr = PartialView("_AddEditUserPartial", ucm);
string s = _helper.ViewToString(this.ControllerContext, pvr, _viewEngine);
return Ok(s);
}
catch (Exception ex)
{
_logger.LogError(ex, "UserClientView Error. userName: {userName}", new[] { ucm.UserLogonName });
return new JsonResult(StatusCode(StatusCodes.Status500InternalServerError));
}
}
Помощник:
public interface IHelper
{
string ViewToString(ControllerContext controllerContext, PartialViewResult pvr, ICompositeViewEngine _viewEngine);
}
public class Helper : IHelper
{
public string ViewToString(ControllerContext controllerContext, PartialViewResult pvr, ICompositeViewEngine _viewEngine)
{
using (var writer = new StringWriter())
{
ViewEngineResult viewResult = _viewEngine.FindView(controllerContext, pvr.ViewName, false);
ViewContext viewContext = new ViewContext(
controllerContext,
viewResult.View,
pvr.ViewData,
pvr.TempData,
writer,
new HtmlHelperOptions()
);
viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
}
Запускать:
services.AddSingleton<IHelper, Helper>();
Var dados = Json(новый {вид = ControllerExtensions.RenderViewAsync (?????, "FecharComanda2", демонстративно, true)});
??? если не объявлен, подпись метода нарушена.
этот контроллер Controller не работает для меня. Я реализовал код, предложенный @Red, но я вызываю метод, я не могу получить экземпляр контроллера
открытый статический класс ControllerExtensions {общедоступная статическая асинхронная задача RenderViewAsync (этот контроллер контроллера, строка viewName, модель TModel, 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();
}
Ткс!
У Microsoft есть отличная статья о тестировании контроллеров на https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/testing
После того, как вы вернули ViewResult, вы можете получить содержимое строки
var strResult = ViewResult.Content