MVC 6 控制器中的 ControllerContext 和 ViewEngines 属性在哪里?
Where are the ControllerContext and ViewEngines properties in MVC 6 Controller?
我创建了一个新的 MVC6 项目并构建了一个新站点。目标是获得视图的渲染结果。我找到了以下代码,但我无法让它工作,因为我找不到 ControllerContext
和 ViewEngines
.
这是我要重写的代码:
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
Update: I'm updating this to work with .Net Core 2.x as the APIs have changed since 2015!
首先,我们可以利用 ASP.Net MVC Core 附带的内置依赖注入,它将为我们提供 ICompositeViewEngine
手动呈现视图所需的对象。因此,例如,控制器看起来像这样:
public class MyController : Controller
{
private ICompositeViewEngine _viewEngine;
public MyController(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
//Rest of the controller code here
}
接下来,我们实际需要渲染视图的代码。请注意,它现在是一个 async
方法,因为我们将在内部进行异步调用:
private async Task<string> RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.ActionName;
ViewData.Model = model;
using (var writer = new StringWriter())
{
ViewEngineResult viewResult =
_viewEngine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
调用方法,就这么简单:
public async Task<IActionResult> Index()
{
var model = new TestModel
{
SomeProperty = "whatever"
}
var renderedView = await RenderPartialViewToString("NameOfView", model);
//Do what you want with the renderedView here
return View();
}
已发布的 dotnet core 1.0 已更改,此版本的上述代码适用于 1.0 RTM。
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.DisplayName;
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
sw,
new HtmlHelperOptions() //Added this parameter in
);
//Everything is async now!
var t = viewResult.View.RenderAsync(viewContext);
t.Wait();
return sw.GetStringBuilder().ToString();
}
}
编译此代码需要这些用法:
using System.IO;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
我还必须向控制器构造函数添加一个 DI 接口:
IServiceProvider serviceProvider
我的帐户构造函数现在看起来像这样:
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IServiceProvider serviceProvider)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_serviceProvider = serviceProvider;
}
Martin Tomes 提供的解决方案对我有用,但我不得不更换:
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
与
ViewEngineResult viewResult = engine.GetView(_env.WebRootPath, viewName, false);
同样在控制器构造函数中必须添加
private IHostingEnvironment _env;
public AccountController(IHostingEnvironment env)
{
_env = env;
}
Martin Tomes 的解决方案效果很好。我的更改:删除了 serviceProvider 并通过 DI 在构造函数中获取 ICompositeViewEngine。
构造函数看起来像:
private readonly ICompositeViewEngine _viewEngine;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
ICompositeViewEngine viewEngine)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_viewEngine = viewEngine;;
}
并放
ViewEngineResult viewResult = _viewEngine.FindView(ControllerContext, viewName, false);
而不是
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
DavidG提供的解决方案很好,但我将其更改为独立服务。
namespace WebApplication.Services
{
public interface IViewRenderService
{
Task<string> RenderPartialViewToString(Controller Controller, string viewName, object model);
}
public class ViewRenderService: IViewRenderService
{
private readonly ICompositeViewEngine _viewEngine;
public ViewRenderService(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
public async Task<string> RenderPartialViewToString(Controller Controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = Controller.ControllerContext.ActionDescriptor.ActionName;
Controller.ViewData.Model = model;
using (var writer = new StringWriter())
{
ViewEngineResult viewResult =
_viewEngine.FindView(Controller.ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
Controller.ControllerContext,
viewResult.View,
Controller.ViewData,
Controller.TempData,
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
}
}
将服务添加到启动:
services.AddScoped<IViewRenderService, ViewRenderService>();
现在像这样使用依赖注入:
public class MyController : Controller
{
private readonly IViewRenderService _viewRender;
public MyController(IViewRenderService viewRender)
{
_viewRender = viewRender;
}
//Rest of the controller code here
}
现在您可以像这样在操作方法中使用它:
var renderedView = await_viewRender.RenderPartialViewToString(this,"nameofview", model);
我创建了一个新的 MVC6 项目并构建了一个新站点。目标是获得视图的渲染结果。我找到了以下代码,但我无法让它工作,因为我找不到 ControllerContext
和 ViewEngines
.
这是我要重写的代码:
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
Update: I'm updating this to work with .Net Core 2.x as the APIs have changed since 2015!
首先,我们可以利用 ASP.Net MVC Core 附带的内置依赖注入,它将为我们提供 ICompositeViewEngine
手动呈现视图所需的对象。因此,例如,控制器看起来像这样:
public class MyController : Controller
{
private ICompositeViewEngine _viewEngine;
public MyController(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
//Rest of the controller code here
}
接下来,我们实际需要渲染视图的代码。请注意,它现在是一个 async
方法,因为我们将在内部进行异步调用:
private async Task<string> RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.ActionName;
ViewData.Model = model;
using (var writer = new StringWriter())
{
ViewEngineResult viewResult =
_viewEngine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
调用方法,就这么简单:
public async Task<IActionResult> Index()
{
var model = new TestModel
{
SomeProperty = "whatever"
}
var renderedView = await RenderPartialViewToString("NameOfView", model);
//Do what you want with the renderedView here
return View();
}
已发布的 dotnet core 1.0 已更改,此版本的上述代码适用于 1.0 RTM。
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.ActionDescriptor.DisplayName;
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
ViewData,
TempData,
sw,
new HtmlHelperOptions() //Added this parameter in
);
//Everything is async now!
var t = viewResult.View.RenderAsync(viewContext);
t.Wait();
return sw.GetStringBuilder().ToString();
}
}
编译此代码需要这些用法:
using System.IO;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
我还必须向控制器构造函数添加一个 DI 接口:
IServiceProvider serviceProvider
我的帐户构造函数现在看起来像这样:
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IServiceProvider serviceProvider)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_serviceProvider = serviceProvider;
}
Martin Tomes 提供的解决方案对我有用,但我不得不更换:
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
与
ViewEngineResult viewResult = engine.GetView(_env.WebRootPath, viewName, false);
同样在控制器构造函数中必须添加
private IHostingEnvironment _env;
public AccountController(IHostingEnvironment env)
{
_env = env;
}
Martin Tomes 的解决方案效果很好。我的更改:删除了 serviceProvider 并通过 DI 在构造函数中获取 ICompositeViewEngine。 构造函数看起来像:
private readonly ICompositeViewEngine _viewEngine;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
ICompositeViewEngine viewEngine)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_viewEngine = viewEngine;;
}
并放
ViewEngineResult viewResult = _viewEngine.FindView(ControllerContext, viewName, false);
而不是
var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; // Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
DavidG提供的解决方案很好,但我将其更改为独立服务。
namespace WebApplication.Services
{
public interface IViewRenderService
{
Task<string> RenderPartialViewToString(Controller Controller, string viewName, object model);
}
public class ViewRenderService: IViewRenderService
{
private readonly ICompositeViewEngine _viewEngine;
public ViewRenderService(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
public async Task<string> RenderPartialViewToString(Controller Controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = Controller.ControllerContext.ActionDescriptor.ActionName;
Controller.ViewData.Model = model;
using (var writer = new StringWriter())
{
ViewEngineResult viewResult =
_viewEngine.FindView(Controller.ControllerContext, viewName, false);
ViewContext viewContext = new ViewContext(
Controller.ControllerContext,
viewResult.View,
Controller.ViewData,
Controller.TempData,
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.GetStringBuilder().ToString();
}
}
}
}
将服务添加到启动:
services.AddScoped<IViewRenderService, ViewRenderService>();
现在像这样使用依赖注入:
public class MyController : Controller
{
private readonly IViewRenderService _viewRender;
public MyController(IViewRenderService viewRender)
{
_viewRender = viewRender;
}
//Rest of the controller code here
}
现在您可以像这样在操作方法中使用它:
var renderedView = await_viewRender.RenderPartialViewToString(this,"nameofview", model);