在MVC 6控制器中的ControllerContext和ViewEngines属性在哪里?

本文关键字:ViewEngines 属性 在哪里 ControllerContext MVC 控制器 | 更新日期: 2023-09-27 18:07:00

我创建了一个新的MVC6项目,并建立了一个新的网站。目标是获得视图的渲染结果。我找到了下面的代码,但我不能让它工作,因为我找不到ControllerContextViewEngines

下面是我想重写的代码:

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();
    }
}

在MVC 6控制器中的ControllerContext和ViewEngines属性在哪里?

Update:我正在更新这个工作与。net Core 2。x,因为api自2015年以来发生了变化!

首先,我们可以利用ASP内置的依赖注入。这将给我们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);

david提供的解决方案运行良好,但我将其更改为独立服务。

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();
                }
            }
}
}

Add service to startup:

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);